Changeset 26401


Ignore:
Timestamp:
06/20/10 15:54:04 (7 years ago)
Author:
flack
Message:

Reorder functions for better readability, refs #359

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/developers/flack/acltuning/midcom.core/midcom/helper/_basicnav.php

    r26399 r26401  
    256256    }
    257257
     258
     259    /**
     260     * This function is the controlling instance of the loading mechanism. It
     261     * is able to load the navigation data of any topic within MidCOM's topic
     262     * tree into memory. Any uplink nodes that are not loaded into memory will
     263     * be loaded until any other known topic is encountered. After the
     264     * necessary data has been loaded with calls to _loadNodeData.
     265     *
     266     * If all load calls were successful, MIDCOM_ERROK is returned. Any error
     267     * will be indicated with a corresponding return value.
     268     *
     269     * @param mixed $node_id    The node ID of the node to be loaded
     270     * @param mixed $up    The node ID of the parent node.    Optional and not normally needed.
     271     * @return int            MIDCOM_ERROK on success, one of the MIDCOM_ERR... constants upon an error
     272     * @access private
     273     */
     274    private function _loadNode($node_id, $up = null)
     275    {
     276        if (   is_object($node_id)
     277            && $node_id->guid)
     278        {
     279            $topic = $node_id;
     280            $node_id = $this->_nodeid($topic->id, $up);
     281
     282            // Check if we have a cached version of the node already
     283            if (isset(self::$_nodes[$node_id]))
     284            {
     285                return MIDCOM_ERROK;
     286            }
     287        }
     288        else
     289        {
     290            // Check if we have a cached version of the node already
     291            if (isset(self::$_nodes[$node_id]))
     292            {
     293                return MIDCOM_ERROK;
     294            }
     295
     296            if (!$up)
     297            {
     298                $up = $this->_up($node_id);
     299            }
     300            $topic_id = (int) $node_id;
     301
     302            $topic = midcom_db_topic::get_cached($topic_id);
     303            if (   !$topic
     304                || !$topic->guid)
     305            {
     306                debug_push_class(__CLASS__, __FUNCTION__);
     307                debug_add("Could not load Topic #{$topic_id}: " . midcom_application::get_error_string(), MIDCOM_LOG_ERROR);
     308                debug_pop();
     309                return MIDCOM_ERRCRIT;
     310            }
     311        }
     312
     313        // Load parent nodes also to cache
     314        $uplinks = array();
     315        $parent = $topic;
     316        $up_ids = array();
     317        if ($up)
     318        {
     319            static $up_parent_cache = array();
     320            if (isset($up_parent_cache[$parent->id]))
     321            {
     322                $parent = $up_parent_cache[$parent->id];
     323            }
     324            else
     325            {
     326                $parent = midcom_db_topic::get_cached($parent->id);
     327                $up_parent_cache[$parent->id] = $parent;
     328            }
     329            $parent->up = (int) $up;
     330
     331            $up_ids = explode("_", $up);
     332            $up_ids = array_reverse($up_ids);
     333            array_pop($up_ids);
     334        }
     335
     336        while (   is_object($parent)
     337               && $parent->guid
     338               && $parent->up != 0
     339               && !isset(self::$_nodes[$parent->id]))
     340        {
     341            $parent = $parent->get_parent();
     342            if (   $parent
     343                && $parent->guid)
     344            {
     345                $uplinks[] = $parent;
     346            }
     347            if ($up)
     348            {
     349                if ($up_id = array_pop($up_ids))
     350                {
     351                    if ($up_id != $parent->up)
     352                    {
     353                        $parent->up = $up_id;
     354                    }
     355                }
     356            }
     357        }
     358
     359        // Ensure root folder is first
     360        $uplinks = array_reverse($uplinks);
     361
     362        $lastgoodnode = null;
     363        foreach ($uplinks as $uptopic)
     364        {
     365            if (array_key_exists($uptopic->id, self::$_nodes))
     366            {
     367                // We already saw this node, no point in loading it again
     368                $lastgoodnode = $uptopic->id;
     369                continue;
     370            }
     371
     372            // Pass the full topic so _loadNodeData doesn't have to reload it
     373            $result = $this->_loadNodeData($uptopic);
     374            switch ($result)
     375            {
     376                case MIDCOM_ERRFORBIDDEN:
     377                    debug_push_class(__CLASS__, __FUNCTION__);
     378                    $log_level = MIDCOM_LOG_WARN;
     379                    if (!$uptopic->up)
     380                    {
     381                        // This can happen only when a target for a symlink pointing outside the tree is tried to be accessed.
     382                        // It is normal then, so use info as log level in that case.
     383                        $log_level = MIDCOM_LOG_INFO;
     384                    }
     385                    debug_add("The Node {$uptopic->id} is invisible, could not satisfy the dependency chain to Node #{$node_id}", $log_level);
     386                    debug_pop();
     387                    return MIDCOM_ERRFORBIDDEN;
     388
     389                case MIDCOM_ERRCRIT:
     390                    return MIDCOM_ERRCRIT;
     391            }
     392
     393            $lastgoodnode = $uptopic->id;
     394        }
     395        if (!is_null($lastgoodnode))
     396        {
     397            if (!isset($this->_lastgoodnode) || !$this->_lastgoodnode || ($this->_lastgoodnode <= 0))
     398            {
     399                $this->_lastgoodnode = $lastgoodnode;
     400            }
     401        }
     402
     403        return $this->_loadNodeData($topic, $up);
     404    }
     405
     406    /**
     407     * Load the Navigational information associated with the topic $param, which
     408     * can be passed as an ID or as a MidgardTopic object. This is differentiated
     409     * by the flag $idmode (true for id, false for MidgardTopic).
     410     *
     411     * This method does query the topic for all information and completes it to
     412     * build up a full NAP data structure
     413     *
     414     * It determines the URL_NAME of the topic automatically using the name of the
     415     * topic in question.
     416     *
     417     * The currently active leaf is only queried if and only if the currently
     418     * processed topic is equal to the current context's content topic. This should
     419     * prevent dynamically loaded components from disrupting active leaf information,
     420     * as this can happen if dynamic_load is called before showing the navigation.
     421     *
     422     * @param mixed $node    Topic to be processed. Object or ID
     423     * @return int            One of the MGD_ERR constants
     424     */
     425    private function _loadNodeData($node, $up = null)
     426    {
     427        // Load the object.
     428        if (!is_object($node))
     429        {
     430            $topic_id = (int) $node;
     431            $topic = midcom_db_topic::get_cached($topic_id);
     432        }
     433        else
     434        {
     435            $topic = $node;
     436            $topic_id = $topic->id;
     437        }
     438
     439        if (   !$topic
     440            || !$topic->guid)
     441        {
     442            debug_push_class(__CLASS__, __FUNCTION__);
     443            debug_add("Could not open Topic: " . midcom_application::get_error_string(), MIDCOM_LOG_ERROR);
     444            debug_pop();
     445            return MIDCOM_ERRCRIT;
     446        }
     447
     448        // Load the node data and check visibility.
     449        $nodedata = $this->_get_node($topic, $up);
     450
     451        if (! $this->_is_object_visible($nodedata))
     452        {
     453            return MIDCOM_ERRFORBIDDEN;
     454        }
     455        // The node is visible, add it to the list.
     456        self::$_nodes[$nodedata[MIDCOM_NAV_ID]] = $nodedata;
     457        $this->_guid_map[$nodedata[MIDCOM_NAV_GUID]] =& self::$_nodes[$nodedata[MIDCOM_NAV_ID]];
     458
     459        // Load the current leaf, this does *not* load the leaves from the DB, this is done
     460        // during get_leaf now.
     461        if ($nodedata[MIDCOM_NAV_ID] === $this->_current)
     462        {
     463            $interface = $this->_loader->get_interface_class($nodedata[MIDCOM_NAV_COMPONENT]);
     464            if (!$interface)
     465            {
     466                debug_push_class(__CLASS__, __FUNCTION__);
     467                debug_add("Could not get interface class of '{$nodedata[MIDCOM_NAV_COMPONENT]}' to the topic {$topic->id}, cannot add it to the NAP list.",
     468                    MIDCOM_LOG_ERROR);
     469                debug_pop();
     470                return null;
     471            }
     472            $currentleaf = $interface->get_current_leaf();
     473            if ($currentleaf !== false)
     474            {
     475                $this->_currentleaf = "{$nodedata[MIDCOM_NAV_ID]}-{$currentleaf}";
     476            }
     477        }
     478
     479        return MIDCOM_ERROK;
     480    }
     481
    258482    /**
    259483     * This helper object will construct a complete node data structure for a given topic,
     
    475699
    476700    /**
     701     * Loads the leaves for a given node from the cache or database.
     702     * It will relay the code to _get_leaves() and check the object visibility upon
     703     * return.
     704     *
     705     * @param Array $node The NAP node data structure to load the nodes for.
     706     */
     707    private function _load_leaves($node)
     708    {
     709        debug_push_class(__CLASS__, __FUNCTION__);
     710
     711        if (in_array($node[MIDCOM_NAV_ID], $this->_loaded_leaves, true))
     712        {
     713            debug_add("Warning, tried to load the leaves of node {$node[MIDCOM_NAV_ID]} more then once.", MIDCOM_LOG_INFO);
     714            debug_pop();
     715            return;
     716        }
     717
     718        debug_add("Loading leaves for node {$node[MIDCOM_NAV_ID]}");
     719
     720        $leaves = $this->_get_leaves($node);
     721        foreach ($leaves as $id => $leaf)
     722        {
     723            if ($this->_is_object_visible($leaf))
     724            {
     725                // The leaf is visible, add it to the list.
     726                $this->_leaves[$id] = $leaf;
     727                $this->_guid_map[$leaf[MIDCOM_NAV_GUID]] =& $this->_leaves[$id];
     728            }
     729        }
     730        $this->_loaded_leaves[] = $node[MIDCOM_NAV_ID];
     731
     732        debug_pop();
     733    }
     734
     735    /**
    477736     * Return the list of leaves for a given node. This helper will construct complete leaf
    478737     * data structures for each leaf found. It will first check the cache for the leaf structures,
     
    525784
    526785        return $leaves;
    527     }
    528 
    529     /**
    530      * This helper updates the URLs in the reference-passed leaf list.
    531      * FULLURL, ABSOLUTEURL and PERMALINK are built upon RELATIVEURL, NAV_NAME
    532      * and NAV_URL are populated based on the administration mode with NAV_SITE values
    533      *
    534      * @param Array $leaves A reference to the list of leaves which has to be processed.
    535      * @access private
    536      */
    537     private function _update_leaflist_urls(&$leaves)
    538     {
    539         $fullprefix = "{$GLOBALS['midcom_config']['midcom_site_url']}";
    540         $absoluteprefix = substr($GLOBALS['midcom_config']['midcom_site_url'], strlen($_MIDCOM->get_host_name()));
    541 
    542         if (! is_array($leaves))
    543         {
    544             debug_push_class(__CLASS__, __FUNCTION__);
    545             debug_print_r("Wrong type", $leaves, MIDCOM_LOG_ERROR);
    546             debug_pop();
    547 
    548             $_MIDCOM->generate_error(MIDCOM_ERRCRIT, 'Wrong type passed for navigation, see error level log for details');
    549             // This will exit
    550         }
    551 
    552         foreach ($leaves as $id => $copy)
    553         {
    554             $leaves[$id][MIDCOM_NAV_FULLURL] = $fullprefix . $leaves[$id][MIDCOM_NAV_RELATIVEURL];
    555             $leaves[$id][MIDCOM_NAV_ABSOLUTEURL] = $absoluteprefix . $leaves[$id][MIDCOM_NAV_RELATIVEURL];
    556 
    557             if (is_null($leaves[$id][MIDCOM_NAV_GUID]))
    558             {
    559                 $leaves[$id][MIDCOM_NAV_PERMALINK] = $leaves[$id][MIDCOM_NAV_FULLURL];
    560             }
    561             else
    562             {
    563                 $leaves[$id][MIDCOM_NAV_PERMALINK] = $_MIDCOM->permalinks->create_permalink($leaves[$id][MIDCOM_NAV_GUID]);
    564             }
    565         }
    566     }
    567 
    568     /**
    569      * Writes the leaves passed to this function to the cache, assigning them to the
    570      * specified node.
    571      *
    572      * The function will bail out on any critical error. Data inconsistencies will be
    573      * logged and overwritten silently otherwise.
    574      *
    575      * @param Array $node The node data structure to which the leaves should be assigned.
    576      * @param Array $leaves The leaves to store in the cache.
    577      * @access private
    578      */
    579     private function _write_leaves_to_cache($node, $leaves)
    580     {
    581         debug_push_class(__CLASS__, __FUNCTION__);
    582         debug_add('Writing ' . count ($leaves) . ' leaves to the cache.');
    583 
    584         // We need to update the node too, as it contains the leaf list for rapid access.
    585         $node_leaflist = array_keys($leaves);
    586 
    587         $this->_nap_cache->open(true);
    588 
    589         if (! $this->_nap_cache->exists($node[MIDCOM_NAV_ID]))
    590         {
    591             $this->_nap_cache->close();
    592             debug_add("NAP Caching Engine: Tried to update the topic {$node[MIDCOM_NAV_NAME]} (#{$node[MIDCOM_NAV_OBJECT]->id}) "
    593                 . 'which was supposed to be in the cache already, but failed to load the object from the database. '
    594                 . 'Aborting write_to_cache, this is a critical cache inconsistency.', MIDCOM_LOG_WARN);
    595             debug_pop();
    596             return;
    597         }
    598 
    599         // We load it again to get the cached structure, not the completed one from the
    600         // in-memory cache.
    601         $cached_node = $this->_nap_cache->get($node[MIDCOM_NAV_ID]);
    602         $cached_node[MIDCOM_NAV_LEAVES] = $node_leaflist;
    603 
    604         debug_print_r('Updating the Node structure in the cache to this:', $cached_node);
    605         $this->_nap_cache->put($node[MIDCOM_NAV_ID], $cached_node);
    606 
    607         $this->_nap_cache->put("{$node[MIDCOM_NAV_ID]}-leaves", $leaves);
    608 
    609         $this->_nap_cache->close();
    610         debug_pop();
    611786    }
    612787
     
    767942
    768943    /**
    769      * Checks, if the NAP object indicated by $napdata is visible within the current
    770      * runtime environment. It will work with both nodes and leaves.
    771      * This includes checks for:
    772      *
    773      * - Nonexistent NAP information (null values)
    774      * - Viewergroups
    775      * - Scheduling/Hiding (only on-site)
    776      * - Approval (only on-site)
    777      *
    778      * @param Array $napdata The NAP data structure for the object to check (supports NULL values).
    779      * @return boolean Indicating visibility.
     944     * This helper updates the URLs in the reference-passed leaf list.
     945     * FULLURL, ABSOLUTEURL and PERMALINK are built upon RELATIVEURL, NAV_NAME
     946     * and NAV_URL are populated based on the administration mode with NAV_SITE values
     947     *
     948     * @param Array $leaves A reference to the list of leaves which has to be processed.
    780949     * @access private
    781      * @todo Integrate with midcom_helper_metadata::is_object_visible_onsite()
    782      */
    783     private function _is_object_visible($napdata)
    784     {
    785         if (is_null($napdata))
     950     */
     951    private function _update_leaflist_urls(&$leaves)
     952    {
     953        $fullprefix = "{$GLOBALS['midcom_config']['midcom_site_url']}";
     954        $absoluteprefix = substr($GLOBALS['midcom_config']['midcom_site_url'], strlen($_MIDCOM->get_host_name()));
     955
     956        if (! is_array($leaves))
    786957        {
    787958            debug_push_class(__CLASS__, __FUNCTION__);
    788             debug_add('Got a null value as napdata, so this object does not have any NAP info, so we cannot display it.');
     959            debug_print_r("Wrong type", $leaves, MIDCOM_LOG_ERROR);
    789960            debug_pop();
    790             return false;
    791         }
    792 
    793         // Check the Metadata if and only if we are configured to do so.
    794         if (   is_object($napdata[MIDCOM_NAV_OBJECT])
    795             && (   $GLOBALS['midcom_config']['show_hidden_objects'] == false
    796                 || $GLOBALS['midcom_config']['show_unapproved_objects'] == false))
    797         {
    798             // Check Hiding, Scheduling and Approval
    799             $metadata = $napdata[MIDCOM_NAV_OBJECT]->metadata;
    800 
    801             if (! $metadata)
    802             {
    803                 // For some reason, the metadata for this object could not be retrieved. so we skip
    804                 // Approval/Visibility checks.
    805                 debug_push_class(__CLASS__, __FUNCTION__);
    806                 debug_add("Warning, no Metadata available for the {$napdata[MIDCOM_NAV_TYPE]} {$napdata[MIDCOM_NAV_GUID]}.", MIDCOM_LOG_INFO);
    807                 debug_pop();
    808                 return true;
    809             }
    810 
    811             if (! $metadata->is_object_visible_onsite())
    812             {
    813                 return false;
    814             }
    815         }
    816 
    817         return true;
    818     }
    819 
    820     /**
    821      * Load the Navigational information associated with the topic $param, which
    822      * can be passed as an ID or as a MidgardTopic object. This is differentiated
    823      * by the flag $idmode (true for id, false for MidgardTopic).
    824      *
    825      * This method does query the topic for all information and completes it to
    826      * build up a full NAP data structure
    827      *
    828      * It determines the URL_NAME of the topic automatically using the name of the
    829      * topic in question.
    830      *
    831      * The currently active leaf is only queried if and only if the currently
    832      * processed topic is equal to the current context's content topic. This should
    833      * prevent dynamically loaded components from disrupting active leaf information,
    834      * as this can happen if dynamic_load is called before showing the navigation.
    835      *
    836      * @param mixed $node    Topic to be processed. Object or ID
    837      * @return int            One of the MGD_ERR constants
    838      */
    839     private function _loadNodeData($node, $up = null)
    840     {
    841         // Load the object.
    842         if (!is_object($node))
    843         {
    844             $topic_id = (int) $node;
    845             $topic = midcom_db_topic::get_cached($topic_id);
    846         }
    847         else
    848         {
    849             $topic = $node;
    850             $topic_id = $topic->id;
    851         }
    852 
    853         if (   !$topic
    854             || !$topic->guid)
    855         {
    856             debug_push_class(__CLASS__, __FUNCTION__);
    857             debug_add("Could not open Topic: " . midcom_application::get_error_string(), MIDCOM_LOG_ERROR);
    858             debug_pop();
    859             return MIDCOM_ERRCRIT;
    860         }
    861 
    862         // Load the node data and check visibility.
    863         $nodedata = $this->_get_node($topic, $up);
    864        
    865         if (! $this->_is_object_visible($nodedata))
    866         {
    867             return MIDCOM_ERRFORBIDDEN;
    868         }
    869         // The node is visible, add it to the list.
    870         self::$_nodes[$nodedata[MIDCOM_NAV_ID]] = $nodedata;
    871         $this->_guid_map[$nodedata[MIDCOM_NAV_GUID]] =& self::$_nodes[$nodedata[MIDCOM_NAV_ID]];
    872 
    873         // Load the current leaf, this does *not* load the leaves from the DB, this is done
    874         // during get_leaf now.
    875         if ($nodedata[MIDCOM_NAV_ID] === $this->_current)
    876         {
    877             $interface = $this->_loader->get_interface_class($nodedata[MIDCOM_NAV_COMPONENT]);
    878             if (!$interface)
    879             {
    880                 debug_push_class(__CLASS__, __FUNCTION__);
    881                 debug_add("Could not get interface class of '{$nodedata[MIDCOM_NAV_COMPONENT]}' to the topic {$topic->id}, cannot add it to the NAP list.",
    882                     MIDCOM_LOG_ERROR);
    883                 debug_pop();
    884                 return null;
    885             }
    886             $currentleaf = $interface->get_current_leaf();
    887             if ($currentleaf !== false)
    888             {
    889                 $this->_currentleaf = "{$nodedata[MIDCOM_NAV_ID]}-{$currentleaf}";
    890             }
    891         }
    892 
    893         return MIDCOM_ERROK;
    894     }
    895 
    896     /**
    897      * Loads the leaves for a given node from the cache or database.
    898      * It will relay the code to _get_leaves() and check the object visibility upon
    899      * return.
    900      *
    901      * @param Array $node The NAP node data structure to load the nodes for.
    902      */
    903     private function _load_leaves($node)
     961
     962            $_MIDCOM->generate_error(MIDCOM_ERRCRIT, 'Wrong type passed for navigation, see error level log for details');
     963            // This will exit
     964        }
     965
     966        foreach ($leaves as $id => $copy)
     967        {
     968            $leaves[$id][MIDCOM_NAV_FULLURL] = $fullprefix . $leaves[$id][MIDCOM_NAV_RELATIVEURL];
     969            $leaves[$id][MIDCOM_NAV_ABSOLUTEURL] = $absoluteprefix . $leaves[$id][MIDCOM_NAV_RELATIVEURL];
     970
     971            if (is_null($leaves[$id][MIDCOM_NAV_GUID]))
     972            {
     973                $leaves[$id][MIDCOM_NAV_PERMALINK] = $leaves[$id][MIDCOM_NAV_FULLURL];
     974            }
     975            else
     976            {
     977                $leaves[$id][MIDCOM_NAV_PERMALINK] = $_MIDCOM->permalinks->create_permalink($leaves[$id][MIDCOM_NAV_GUID]);
     978            }
     979        }
     980    }
     981
     982    /**
     983     * Writes the leaves passed to this function to the cache, assigning them to the
     984     * specified node.
     985     *
     986     * The function will bail out on any critical error. Data inconsistencies will be
     987     * logged and overwritten silently otherwise.
     988     *
     989     * @param Array $node The node data structure to which the leaves should be assigned.
     990     * @param Array $leaves The leaves to store in the cache.
     991     * @access private
     992     */
     993    private function _write_leaves_to_cache($node, $leaves)
    904994    {
    905995        debug_push_class(__CLASS__, __FUNCTION__);
    906 
    907         if (in_array($node[MIDCOM_NAV_ID], $this->_loaded_leaves, true))
    908         {
    909             debug_add("Warning, tried to load the leaves of node {$node[MIDCOM_NAV_ID]} more then once.", MIDCOM_LOG_INFO);
     996        debug_add('Writing ' . count ($leaves) . ' leaves to the cache.');
     997
     998        // We need to update the node too, as it contains the leaf list for rapid access.
     999        $node_leaflist = array_keys($leaves);
     1000
     1001        $this->_nap_cache->open(true);
     1002
     1003        if (! $this->_nap_cache->exists($node[MIDCOM_NAV_ID]))
     1004        {
     1005            $this->_nap_cache->close();
     1006            debug_add("NAP Caching Engine: Tried to update the topic {$node[MIDCOM_NAV_NAME]} (#{$node[MIDCOM_NAV_OBJECT]->id}) "
     1007                . 'which was supposed to be in the cache already, but failed to load the object from the database. '
     1008                . 'Aborting write_to_cache, this is a critical cache inconsistency.', MIDCOM_LOG_WARN);
    9101009            debug_pop();
    9111010            return;
    9121011        }
    9131012
    914         debug_add("Loading leaves for node {$node[MIDCOM_NAV_ID]}");
    915 
    916         $leaves = $this->_get_leaves($node);
    917         foreach ($leaves as $id => $leaf)
    918         {
    919             if ($this->_is_object_visible($leaf))
    920             {
    921                 // The leaf is visible, add it to the list.
    922                 $this->_leaves[$id] = $leaf;
    923                 $this->_guid_map[$leaf[MIDCOM_NAV_GUID]] =& $this->_leaves[$id];
    924             }
    925         }
    926         $this->_loaded_leaves[] = $node[MIDCOM_NAV_ID];
    927 
     1013        // We load it again to get the cached structure, not the completed one from the
     1014        // in-memory cache.
     1015        $cached_node = $this->_nap_cache->get($node[MIDCOM_NAV_ID]);
     1016        $cached_node[MIDCOM_NAV_LEAVES] = $node_leaflist;
     1017
     1018        debug_print_r('Updating the Node structure in the cache to this:', $cached_node);
     1019        $this->_nap_cache->put($node[MIDCOM_NAV_ID], $cached_node);
     1020
     1021        $this->_nap_cache->put("{$node[MIDCOM_NAV_ID]}-leaves", $leaves);
     1022
     1023        $this->_nap_cache->close();
    9281024        debug_pop();
    929     }
    930 
    931     /**
    932      * This function is the controlling instance of the loading mechanism. It
    933      * is able to load the navigation data of any topic within MidCOM's topic
    934      * tree into memory. Any uplink nodes that are not loaded into memory will
    935      * be loaded until any other known topic is encountered. After the
    936      * necessary data has been loaded with calls to _loadNodeData.
    937      *
    938      * If all load calls were successful, MIDCOM_ERROK is returned. Any error
    939      * will be indicated with a corresponding return value.
    940      *
    941      * @param mixed $node_id    The node ID of the node to be loaded
    942      * @param mixed $up    The node ID of the parent node.    Optional and not normally needed.
    943      * @return int            MIDCOM_ERROK on success, one of the MIDCOM_ERR... constants upon an error
    944      * @access private
    945      */
    946     private function _loadNode($node_id, $up = null)
    947     {
    948         if (   is_object($node_id)
    949             && $node_id->guid)
    950         {
    951             $topic = $node_id;
    952             $node_id = $this->_nodeid($topic->id, $up);
    953 
    954             // Check if we have a cached version of the node already
    955             if (isset(self::$_nodes[$node_id]))
    956             {
    957                 return MIDCOM_ERROK;
    958             }
    959         }
    960         else
    961         {
    962             // Check if we have a cached version of the node already
    963             if (isset(self::$_nodes[$node_id]))
    964             {
    965                 return MIDCOM_ERROK;
    966             }
    967 
    968             if (!$up)
    969             {
    970                 $up = $this->_up($node_id);
    971             }
    972             $topic_id = (int) $node_id;
    973 
    974             $topic = midcom_db_topic::get_cached($topic_id);
    975             if (   !$topic
    976                 || !$topic->guid)
    977             {
    978                 debug_push_class(__CLASS__, __FUNCTION__);
    979                 debug_add("Could not load Topic #{$topic_id}: " . midcom_application::get_error_string(), MIDCOM_LOG_ERROR);
    980                 debug_pop();
    981                 return MIDCOM_ERRCRIT;
    982             }
    983         }
    984 
    985         // Load parent nodes also to cache
    986         $uplinks = array();
    987         $parent = $topic;
    988         $up_ids = array();
    989         if ($up)
    990         {
    991             static $up_parent_cache = array();
    992             if (isset($up_parent_cache[$parent->id]))
    993             {
    994                 $parent = $up_parent_cache[$parent->id];
    995             }
    996             else
    997             {
    998                 $parent = midcom_db_topic::get_cached($parent->id);
    999                 $up_parent_cache[$parent->id] = $parent;
    1000             }
    1001             $parent->up = (int) $up;
    1002 
    1003             $up_ids = explode("_", $up);
    1004             $up_ids = array_reverse($up_ids);
    1005             array_pop($up_ids);
    1006         }
    1007 
    1008         while (   is_object($parent)
    1009                && $parent->guid
    1010                && $parent->up != 0
    1011                && !isset(self::$_nodes[$parent->id]))
    1012         {
    1013             $parent = $parent->get_parent();
    1014             if (   $parent
    1015                 && $parent->guid)
    1016             {
    1017                 $uplinks[] = $parent;
    1018             }
    1019             if ($up)
    1020             {
    1021                 if ($up_id = array_pop($up_ids))
    1022                 {
    1023                     if ($up_id != $parent->up)
    1024                     {
    1025                         $parent->up = $up_id;
    1026                     }
    1027                 }
    1028             }
    1029         }
    1030 
    1031         // Ensure root folder is first
    1032         $uplinks = array_reverse($uplinks);
    1033 
    1034         $lastgoodnode = null;
    1035         foreach ($uplinks as $uptopic)
    1036         {
    1037             if (array_key_exists($uptopic->id, self::$_nodes))
    1038             {
    1039                 // We already saw this node, no point in loading it again
    1040                 $lastgoodnode = $uptopic->id;
    1041                 continue;
    1042             }
    1043 
    1044             // Pass the full topic so _loadNodeData doesn't have to reload it
    1045             $result = $this->_loadNodeData($uptopic);
    1046             switch ($result)
    1047             {
    1048                 case MIDCOM_ERRFORBIDDEN:
    1049                     debug_push_class(__CLASS__, __FUNCTION__);
    1050                     $log_level = MIDCOM_LOG_WARN;
    1051                     if (!$uptopic->up)
    1052                     {
    1053                         // This can happen only when a target for a symlink pointing outside the tree is tried to be accessed.
    1054                         // It is normal then, so use info as log level in that case.
    1055                         $log_level = MIDCOM_LOG_INFO;
    1056                     }
    1057                     debug_add("The Node {$uptopic->id} is invisible, could not satisfy the dependency chain to Node #{$node_id}", $log_level);
    1058                     debug_pop();
    1059                     return MIDCOM_ERRFORBIDDEN;
    1060 
    1061                 case MIDCOM_ERRCRIT:
    1062                     return MIDCOM_ERRCRIT;
    1063             }
    1064 
    1065             $lastgoodnode = $uptopic->id;
    1066         }
    1067         if (!is_null($lastgoodnode))
    1068         {
    1069             if (!isset($this->_lastgoodnode) || !$this->_lastgoodnode || ($this->_lastgoodnode <= 0))
    1070             {
    1071                 $this->_lastgoodnode = $lastgoodnode;
    1072             }
    1073         }
    1074 
    1075         return $this->_loadNodeData($topic, $up);
    1076     }
    1077 
    1078     /**
    1079      * Retrieve the ID of the currently displayed node. Defined by the topic of
    1080      * the component that declared able to handle the request.
    1081      *
    1082      * @return mixed    The ID of the node in question.
    1083      */
    1084     // Keep this doc in sync with midcom_helper_nav
    1085     function get_current_node()
    1086     {
    1087         return $this->_current;
    1088     }
    1089 
    1090     /**
    1091      * Retrieve the ID of the currently displayed leaf. This is a leaf that is
    1092      * displayed by the handling topic. If no leaf is active, this function
    1093      * returns FALSE. (Remember to make a type sensitive check, e.g.
    1094      * nav::get_current_leaf() !== false to distinguish "0" and "false".)
    1095      *
    1096      * @return string    The ID of the leaf in question or false on failure.
    1097      */
    1098     // Keep this doc in sync with midcom_helper_nav
    1099     function get_current_leaf()
    1100     {
    1101         return $this->_currentleaf;
    1102     }
    1103 
    1104     /**
    1105      * Retrieve the ID of the root node. Note that this ID is dependent from the
    1106      * ID of the MidCOM Root topic and therefore will change as easily as the
    1107      * root topic ID might. The MIDCOM_NAV_URL entry of the root node's data will
    1108      * always be empty.
    1109      *
    1110      * @return int    The ID of the root node.
    1111      */
    1112     // Keep this doc in sync with midcom_helper_nav
    1113     function get_root_node()
    1114     {
    1115         return $this->_root;
    11161025    }
    11171026
     
    11631072
    11641073        $mc->add_order('metadata.score', 'DESC');
    1165         $mc->add_order('metadata.created'); 
     1074        $mc->add_order('metadata.created');
    11661075        $mc->execute();
    11671076        $subnodes = $mc->list_keys();
     
    13081217
    13091218    /**
     1219     * This is a helper function used by midcom_helper_nav::resolve_guid(). It
     1220     * checks if the object denoted by the passed GUID is already loaded into
     1221     * memory and returns it, if available. This should speed up GUID lookup heavy
     1222     * code.
     1223     *
     1224     * Access is restricted to midcom_helper_nav::resolve_guid().
     1225     *
     1226     * @access protected
     1227     * @param GUID $guid The GUID to look up in the in-memory cache.
     1228     * @return Array A NAP structure if the GUID is known, null otherwise.
     1229     */
     1230    function get_loaded_object_by_guid($guid)
     1231    {
     1232        if (! array_key_exists($guid, $this->_guid_map))
     1233        {
     1234            return null;
     1235        }
     1236        return $this->_guid_map[$guid];
     1237    }
     1238
     1239    /**
    13101240     * This will give you a key-value pair describing the node with the ID
    13111241     * $node_id. The defined keys are described above in Node data interchange
     
    13411271
    13421272    /**
    1343      * Verifies the existence of a given leaf. Call this before getting a leaf from the
    1344      * $_leaves cache. It will load all necessary nodes/leaves as necessary.
    1345      *
    1346      * @param string $leaf_id A valid NAP leaf id ($nodeid-$leafid pattern).
    1347      * @return boolean true if the leaf exists, false otherwise.
    1348      */
    1349     private function _check_leaf_id($leaf_id)
    1350     {
    1351          if (! $leaf_id)
    1352          {
    1353             debug_add("Tried to load a suspicious leaf id, probably a FALSE from get_current_leaf.");
    1354             return false;
    1355         }
    1356 
    1357         if (array_key_exists($leaf_id, $this->_leaves))
    1358         {
    1359             return true;
    1360         }
    1361 
    1362         $id_elements = explode('-', $leaf_id);
    1363 
    1364         $node_id = $id_elements[0];
    1365 
    1366         if (   !isset(self::$_nodes[$node_id])
    1367             && $this->_loadNode($node_id) != MIDCOM_ERROK)
    1368         {
    1369             debug_add("Tried to verify the leaf id {$leaf_id}, which should belong to node {$node_id}, but this node cannot be loaded, see debug level log for details.",
    1370                 MIDCOM_LOG_INFO);
    1371             return false;
    1372         }
    1373 
    1374         $this->_load_leaves(self::$_nodes[$node_id]);
    1375 
    1376         return (array_key_exists($leaf_id, $this->_leaves));
    1377     }
    1378 
    1379     /**
    1380      * This will give you a key-value pair describeing the leaf with the ID
     1273     * This will give you a key-value pair describing the leaf with the ID
    13811274     * $node_id. The defined keys are described above in leaf data interchange
    13821275     * format. You will get false if the leaf ID is invalid.
     
    14001293
    14011294    /**
    1402      * This is a helper function used by midcom_helper_nav::resolve_guid(). It
    1403      * checks if the object denoted by the passed GUID is already loaded into
    1404      * memory and returns it, if available. This should speed up GUID lookup heavy
    1405      * code.
    1406      *
    1407      * Access is restricted to midcom_helper_nav::resolve_guid().
    1408      *
    1409      * @access protected
    1410      * @param GUID $guid The GUID to look up in the in-memory cache.
    1411      * @return Array A NAP structure if the GUID is known, null otherwise.
    1412      */
    1413     function get_loaded_object_by_guid($guid)
    1414     {
    1415         if (! array_key_exists($guid, $this->_guid_map))
    1416         {
    1417             return null;
    1418         }
    1419         return $this->_guid_map[$guid];
     1295     * Retrieve the ID of the currently displayed node. Defined by the topic of
     1296     * the component that declared able to handle the request.
     1297     *
     1298     * @return mixed    The ID of the node in question.
     1299     */
     1300    // Keep this doc in sync with midcom_helper_nav
     1301    function get_current_node()
     1302    {
     1303        return $this->_current;
     1304    }
     1305
     1306    /**
     1307     * Retrieve the ID of the currently displayed leaf. This is a leaf that is
     1308     * displayed by the handling topic. If no leaf is active, this function
     1309     * returns FALSE. (Remember to make a type sensitive check, e.g.
     1310     * nav::get_current_leaf() !== false to distinguish "0" and "false".)
     1311     *
     1312     * @return string    The ID of the leaf in question or false on failure.
     1313     */
     1314    // Keep this doc in sync with midcom_helper_nav
     1315    function get_current_leaf()
     1316    {
     1317        return $this->_currentleaf;
     1318    }
     1319
     1320    /**
     1321     * Retrieve the ID of the upper node of the currently displayed node.
     1322     *
     1323     * @return mixed    The ID of the node in question.
     1324     */
     1325    // Keep this doc in sync with midcom_helper_nav
     1326    function get_current_upper_node()
     1327    {
     1328        static $upper_node = null;
     1329
     1330        if (!$upper_node)
     1331        {
     1332            $node = null;
     1333            foreach ($this->_node_path as $node_path_component)
     1334            {
     1335                $upper_node = $node;
     1336                $node = $node_path_component;
     1337            }
     1338            if (!$upper_node)
     1339            {
     1340                $upper_node = $node;
     1341            }
     1342        }
     1343
     1344        return $upper_node;
     1345    }
     1346
     1347    /**
     1348     * Retrieve the ID of the root node. Note that this ID is dependent from the
     1349     * ID of the MidCOM Root topic and therefore will change as easily as the
     1350     * root topic ID might. The MIDCOM_NAV_URL entry of the root node's data will
     1351     * always be empty.
     1352     *
     1353     * @return int    The ID of the root node.
     1354     */
     1355    // Keep this doc in sync with midcom_helper_nav
     1356    function get_root_node()
     1357    {
     1358        return $this->_root;
     1359    }
     1360
     1361    /**
     1362     * Retrieve the IDs of the nodes from the URL. First value at key 0 is
     1363     * the root node ID, possible second value is the first subnode ID etc.
     1364     * Contains only visible nodes (nodes which can be loaded).
     1365     *
     1366     * @return Array    The node path array.
     1367     */
     1368    // Keep this doc in sync with midcom_helper_nav
     1369    function get_node_path()
     1370    {
     1371        return $this->_node_path;
    14201372    }
    14211373
     
    15141466
    15151467    /**
    1516      * Retrieve the IDs of the nodes from the URL. First value at key 0 is
    1517      * the root node ID, possible second value is the first subnode ID etc.
    1518      * Contains only visible nodes (nodes which can be loaded).
    1519      *
    1520      * @return Array    The node path array.
    1521      */
    1522     // Keep this doc in sync with midcom_helper_nav
    1523     function get_node_path()
    1524     {
    1525         return $this->_node_path;
    1526     }
    1527 
    1528     /**
    1529      * Retrieve the ID of the upper node of the currently displayed node.
    1530      *
    1531      * @return mixed    The ID of the node in question.
    1532      */
    1533     // Keep this doc in sync with midcom_helper_nav
    1534     function get_current_upper_node()
    1535     {
    1536         static $upper_node = null;
    1537 
    1538         if (!$upper_node)
    1539         {
    1540             $node = null;
    1541             foreach ($this->_node_path as $node_path_component)
    1542             {
    1543                 $upper_node = $node;
    1544                 $node = $node_path_component;
    1545             }
    1546         if (!$upper_node)
    1547             {
    1548                 $upper_node = $node;
    1549             }
    1550         }
    1551 
    1552         return $upper_node;
     1468     * Verifies the existence of a given leaf. Call this before getting a leaf from the
     1469     * $_leaves cache. It will load all necessary nodes/leaves as necessary.
     1470     *
     1471     * @param string $leaf_id A valid NAP leaf id ($nodeid-$leafid pattern).
     1472     * @return boolean true if the leaf exists, false otherwise.
     1473     */
     1474    private function _check_leaf_id($leaf_id)
     1475    {
     1476         if (! $leaf_id)
     1477         {
     1478            debug_add("Tried to load a suspicious leaf id, probably a FALSE from get_current_leaf.");
     1479            return false;
     1480        }
     1481
     1482        if (array_key_exists($leaf_id, $this->_leaves))
     1483        {
     1484            return true;
     1485        }
     1486
     1487        $id_elements = explode('-', $leaf_id);
     1488
     1489        $node_id = $id_elements[0];
     1490
     1491        if (   !isset(self::$_nodes[$node_id])
     1492            && $this->_loadNode($node_id) != MIDCOM_ERROK)
     1493        {
     1494            debug_add("Tried to verify the leaf id {$leaf_id}, which should belong to node {$node_id}, but this node cannot be loaded, see debug level log for details.",
     1495                MIDCOM_LOG_INFO);
     1496            return false;
     1497        }
     1498
     1499        $this->_load_leaves(self::$_nodes[$node_id]);
     1500
     1501        return (array_key_exists($leaf_id, $this->_leaves));
     1502    }
     1503
     1504
     1505    /**
     1506     * Checks, if the NAP object indicated by $napdata is visible within the current
     1507     * runtime environment. It will work with both nodes and leaves.
     1508     * This includes checks for:
     1509     *
     1510     * - Nonexistent NAP information (null values)
     1511     * - Viewergroups
     1512     * - Scheduling/Hiding (only on-site)
     1513     * - Approval (only on-site)
     1514     *
     1515     * @param Array $napdata The NAP data structure for the object to check (supports NULL values).
     1516     * @return boolean Indicating visibility.
     1517     * @access private
     1518     * @todo Integrate with midcom_helper_metadata::is_object_visible_onsite()
     1519     */
     1520    private function _is_object_visible($napdata)
     1521    {
     1522        if (is_null($napdata))
     1523        {
     1524            debug_push_class(__CLASS__, __FUNCTION__);
     1525            debug_add('Got a null value as napdata, so this object does not have any NAP info, so we cannot display it.');
     1526            debug_pop();
     1527            return false;
     1528        }
     1529
     1530        // Check the Metadata if and only if we are configured to do so.
     1531        if (   is_object($napdata[MIDCOM_NAV_OBJECT])
     1532            && (   $GLOBALS['midcom_config']['show_hidden_objects'] == false
     1533                || $GLOBALS['midcom_config']['show_unapproved_objects'] == false))
     1534        {
     1535            // Check Hiding, Scheduling and Approval
     1536            $metadata = $napdata[MIDCOM_NAV_OBJECT]->metadata;
     1537
     1538            if (! $metadata)
     1539            {
     1540                // For some reason, the metadata for this object could not be retrieved. so we skip
     1541                // Approval/Visibility checks.
     1542                debug_push_class(__CLASS__, __FUNCTION__);
     1543                debug_add("Warning, no Metadata available for the {$napdata[MIDCOM_NAV_TYPE]} {$napdata[MIDCOM_NAV_GUID]}.", MIDCOM_LOG_INFO);
     1544                debug_pop();
     1545                return true;
     1546            }
     1547
     1548            if (! $metadata->is_object_visible_onsite())
     1549            {
     1550                return false;
     1551            }
     1552        }
     1553
     1554        return true;
    15531555    }
    15541556}
Note: See TracChangeset for help on using the changeset viewer.