Complex classes like midcom_helper_nav often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use midcom_helper_nav, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 26 | class midcom_helper_nav |
||
|
1 ignored issue
–
show
|
|||
| 27 | { |
||
| 28 | /** |
||
| 29 | * A reference to the backend instance in use. |
||
| 30 | * |
||
| 31 | * @var midcom_helper_nav_backend |
||
| 32 | */ |
||
| 33 | private $_backend; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * The cache of instantiated NAP backends |
||
| 37 | * |
||
| 38 | * @var array |
||
| 39 | */ |
||
| 40 | private static $_backends = array(); |
||
| 41 | |||
| 42 | /** |
||
| 43 | * The context ID we're associated with. |
||
| 44 | * |
||
| 45 | * @var int |
||
| 46 | */ |
||
| 47 | private $_contextid; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Create a NAP instance for the given context. If unspecified, it |
||
| 51 | * uses the currently active context which should be sufficient |
||
| 52 | * in most cases. |
||
| 53 | * |
||
| 54 | * @param int $contextid The id of the context you want to navigate. |
||
| 55 | */ |
||
| 56 | public function __construct($contextid = -1) |
||
| 65 | |||
| 66 | /** |
||
| 67 | * This function maintains one NAP Class per context. Usually this is enough, |
||
| 68 | * since you mostly will access it in context 0, the default. The problem is, that |
||
| 69 | * this is not 100% efficient: If you instantiate two different NAP Classes in |
||
| 70 | * different contexts both referring to the same root node, you will get two |
||
| 71 | * different instances. |
||
| 72 | * |
||
| 73 | * @return midcom_helper_nav_backend& A reference to the backend instance in the cache. |
||
| 74 | * @see midcom_helper_nav |
||
| 75 | */ |
||
| 76 | private function & _get_backend() |
||
| 85 | |||
| 86 | /* The following methods are just interfaces to midcom_helper_nav_backend */ |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Retrieve the ID of the currently displayed node. Defined by the topic of |
||
| 90 | * the component that declared able to handle the request. |
||
| 91 | * |
||
| 92 | * @return int The ID of the node in question. |
||
| 93 | * @see midcom_helper_nav_backend::get_current_node() |
||
| 94 | */ |
||
| 95 | public function get_current_node() |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Retrieve the ID of the currently displayed leaf. This is a leaf that is |
||
| 102 | * displayed by the handling topic. If no leaf is active, this function |
||
| 103 | * returns false. (Remember to make a type sensitive check, e.g. |
||
| 104 | * nav::get_current_leaf() !== false to distinguish '0' and 'false'.) |
||
| 105 | * |
||
| 106 | * @return int The ID of the leaf in question or false on failure. |
||
| 107 | * @see midcom_helper_nav_backend::get_current_leaf() |
||
| 108 | */ |
||
| 109 | public function get_current_leaf() |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Retrieve the ID of the root node. Note that this ID is dependent from the |
||
| 116 | * ID of the MidCOM Root topic and therefore will change as easily as the |
||
| 117 | * root topic ID might. The MIDCOM_NAV_URL entry of the root node's data will |
||
| 118 | * always be empty. |
||
| 119 | * |
||
| 120 | * @return int The ID of the root node. |
||
| 121 | * @see midcom_helper_nav_backend::get_root_node() |
||
| 122 | */ |
||
| 123 | public function get_root_node() |
||
| 127 | |||
| 128 | /** |
||
| 129 | * Lists all Sub-nodes of $parent_node. If there are no subnodes you will get |
||
| 130 | * an empty array, if there was an error (for instance an unknown parent node |
||
| 131 | * ID) you will get false. |
||
| 132 | * |
||
| 133 | * @param int $parent_node The id of the node of which the subnodes are searched. |
||
| 134 | * @param boolean $show_noentry Show all objects on-site which have the noentry flag set. |
||
| 135 | * This defaults to false. |
||
| 136 | * @return Array An Array of Node IDs or false on failure. |
||
| 137 | * @see midcom_helper_nav_backend::list_nodes() |
||
| 138 | */ |
||
| 139 | public function list_nodes($parent_node, $show_noentry = false) |
||
| 143 | |||
| 144 | /** |
||
| 145 | * Lists all leaves of $parent_node. If there are no leaves you will get an |
||
| 146 | * empty array, if there was an error (for instance an unknown parent node ID) |
||
| 147 | * you will get false. |
||
| 148 | * |
||
| 149 | * @param int $parent_node The ID of the node of which the leaves are searched. |
||
| 150 | * @param boolean $show_noentry Show all objects on-site which have the noentry flag set. |
||
| 151 | * This defaults to false. |
||
| 152 | * @return Array A list of leaves found, or false on failure. |
||
| 153 | * @see midcom_helper_nav_backend::list_leaves() |
||
| 154 | */ |
||
| 155 | public function list_leaves($parent_node, $show_noentry = false) |
||
| 159 | |||
| 160 | /** |
||
| 161 | * This will give you a key-value pair describing the node with the ID |
||
| 162 | * $node_id. The defined keys are described above in Node data interchange |
||
| 163 | * format. You will get false if the node ID is invalid. |
||
| 164 | * |
||
| 165 | * @param int $node_id The node ID to be retrieved. |
||
| 166 | * @return Array The node data as outlined in the class introduction, false on failure |
||
| 167 | * @see midcom_helper_nav_backend::get_node() |
||
| 168 | */ |
||
| 169 | public function get_node($node_id) |
||
| 173 | |||
| 174 | /** |
||
| 175 | * This will give you a key-value pair describing the leaf with the ID |
||
| 176 | * $node_id. The defined keys are described above in leaf data interchange |
||
| 177 | * format. You will get false if the leaf ID is invalid. |
||
| 178 | * |
||
| 179 | * @param string $leaf_id The leaf-id to be retrieved. |
||
| 180 | * @return Array The leaf-data as outlined in the class introduction, false on failure |
||
| 181 | * @see midcom_helper_nav_backend::get_leaf() |
||
| 182 | */ |
||
| 183 | public function get_leaf($leaf_id) |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Returns the ID of the node to which $leaf_id is associated to, false |
||
| 190 | * on failure. |
||
| 191 | * |
||
| 192 | * @param string $leaf_id The Leaf-ID to search an uplink for. |
||
| 193 | * @return int The ID of the Node for which we have a match, or false on failure. |
||
| 194 | * @see midcom_helper_nav_backend::get_leaf_uplink() |
||
| 195 | */ |
||
| 196 | function get_leaf_uplink ($leaf_id) |
||
| 200 | |||
| 201 | /** |
||
| 202 | * Returns the ID of the node to which $node_id is associated to, false |
||
| 203 | * on failure. The root node's uplink is -1. |
||
| 204 | * |
||
| 205 | * @param int $node_id The Leaf-ID to search an uplink for. |
||
| 206 | * @return int The ID of the Node for which we have a match, -1 for the root node, or false on failure. |
||
| 207 | * @see midcom_helper_nav_backend::get_node_uplink() |
||
| 208 | */ |
||
| 209 | public function get_node_uplink($node_id) |
||
| 213 | |||
| 214 | /** |
||
| 215 | * Checks if the given node is within the tree of another node. |
||
| 216 | * |
||
| 217 | * @param int $node_id The node in question. |
||
| 218 | * @param int $root_id The root node to use. |
||
| 219 | * @return boolean True, if the node is a subnode of the root node, false otherwise. |
||
| 220 | */ |
||
| 221 | public function is_node_in_tree($node_id, $root_id) |
||
| 235 | |||
| 236 | /** |
||
| 237 | * List all child elements, nodes and leaves alike, of the node with ID |
||
| 238 | * $parent_node_id. For every child element, an array of ID and type (node/leaf) |
||
| 239 | * is given as |
||
| 240 | * |
||
| 241 | * - MIDCOM_NAV_ID => 0, |
||
| 242 | * - MIDCOM_NAV_TYPE => 'node' |
||
| 243 | * |
||
| 244 | * If there are no child elements at all the method will return an empty array, |
||
| 245 | * in case of an error false. NOTE: This method should be quite slow, there's |
||
| 246 | * room for improvement... :-) |
||
| 247 | * |
||
| 248 | * @param int $parent_node_id The ID of the parent node. |
||
| 249 | * @return Array A list of found elements, or false on failure. |
||
| 250 | */ |
||
| 251 | public function list_child_elements($parent_node_id) |
||
| 282 | |||
| 283 | /** |
||
| 284 | * Try to resolve a guid into a NAP object. |
||
| 285 | * |
||
| 286 | * The code is optimized trying to avoid a full-scan if possible. To do this it |
||
| 287 | * will treat topic and article guids specially: In both cases the system will |
||
| 288 | * translate it using the topic id into a node id and scan only that part of the |
||
| 289 | * tree non-recursively. |
||
| 290 | * |
||
| 291 | * A full scan of the NAP data is only done if another MidgardObject is used. |
||
| 292 | * |
||
| 293 | * Note: If you want to resolve a GUID you got from a Permalink, use the Permalinks |
||
| 294 | * service within MidCOM, as it covers more objects than the NAP listings. |
||
| 295 | * |
||
| 296 | * @param string $guid The GUID of the object to be looked up. |
||
| 297 | * @param boolean $node_is_sufficient if we could return a good guess of correct parent node but said node does not list the $guid in leaves return the node or try to do a full (and very expensive) NAP scan ? |
||
| 298 | * @return mixed Either a node or leaf structure, distinguishable by MIDCOM_NAV_TYPE, or false on failure. |
||
| 299 | * @see midcom_services_permalinks |
||
| 300 | */ |
||
| 301 | public function resolve_guid($guid, $node_is_sufficient = false) |
||
| 392 | |||
| 393 | private function _find_leaf_in_topic($topic, $guid) |
||
| 405 | |||
| 406 | public function find_closest_topic($object) |
||
| 429 | |||
| 430 | /* The more complex interface methods starts here */ |
||
| 431 | |||
| 432 | /** |
||
| 433 | * Construct a breadcrumb line. |
||
| 434 | * |
||
| 435 | * Gives you a line like 'Start > Topic1 > Topic2 > Article' using NAP to |
||
| 436 | * traverse upwards till the root node. $separator is inserted between the |
||
| 437 | * pairs, $class, if non-null, will be used as CSS-class for the A-Tags. |
||
| 438 | * |
||
| 439 | * The parameter skip_levels indicates how much nodes should be skipped at |
||
| 440 | * the beginning of the current path. Default is to show the complete path. A |
||
| 441 | * value of 1 will skip the home link, 2 will skip the home link and the first |
||
| 442 | * subtopic and so on. If a leaf or node is selected, that normally would be |
||
| 443 | * hidden, only its name will be shown. |
||
| 444 | * |
||
| 445 | * @param string $separator The separator to use between the elements. |
||
| 446 | * @param string $class If not-null, it will be assigned to all A tags. |
||
| 447 | * @param int $skip_levels The number of topic levels to skip before starting to work (use this to skip 'Home' links etc.). |
||
| 448 | * @param string $current_class The class that should be assigned to the currently active element. |
||
| 449 | * @param array $skip_guids Array of guids that are skipped. |
||
| 450 | * @return string The computed breadcrumb line. |
||
| 451 | */ |
||
| 452 | public function get_breadcrumb_line($separator = ' > ', $class = null, $skip_levels = 0, $current_class = null, $skip_guids = array()) |
||
| 501 | |||
| 502 | /** |
||
| 503 | * Construct source data for a breadcrumb line. |
||
| 504 | * |
||
| 505 | * Gives you the data needed to construct a line like |
||
| 506 | * 'Start > Topic1 > Topic2 > Article' using NAP to |
||
| 507 | * traverse upwards till the root node. The components custom breadcrumb |
||
| 508 | * data is inserted at the end of the computed breadcrumb line after any |
||
| 509 | * set NAP leaf. |
||
| 510 | * |
||
| 511 | * See get_breadcrumb_line for a more end-user oriented way of life. |
||
| 512 | * |
||
| 513 | * <b>Return Value</b> |
||
| 514 | * |
||
| 515 | * The breadcrumb data will be returned as a list of associative arrays each |
||
| 516 | * containing these keys: |
||
| 517 | * |
||
| 518 | * - MIDCOM_NAV_URL The fully qualified URL to the node. |
||
| 519 | * - MIDCOM_NAV_NAME The clear-text name of the node. |
||
| 520 | * - MIDCOM_NAV_TYPE One of 'node', 'leaf', 'custom' indicating what type of entry |
||
| 521 | * this is. |
||
| 522 | * - MIDCOM_NAV_ID The Identifier of the structure used to build this entry, this is |
||
| 523 | * either a NAP node/leaf ID or the list key set by the component for custom data. |
||
| 524 | * - 'napobject' This contains the original NAP object retrieved by the function. |
||
| 525 | * Just in case you need more information than is available directly. |
||
| 526 | * |
||
| 527 | * The entry of every level is indexed by its MIDCOM_NAV_ID, where custom keys preserve |
||
| 528 | * their original key (as passed by the component) and prefixing it with 'custom-'. This |
||
| 529 | * allows you to easily check if a given node/leave is within the current breadcrumb-line |
||
| 530 | * by checking with array_key_exists. |
||
| 531 | * |
||
| 532 | * <b>Adding custom data</b> |
||
| 533 | * |
||
| 534 | * Custom elements are added to this array by using the MidCOM custom component context |
||
| 535 | * at this time. You need to add a list with the same structure as above into the |
||
| 536 | * custom component context key <i>midcom.helper.nav.breadcrumb</i>. (This needs |
||
| 537 | * to be an array always, even if you return only one element.) |
||
| 538 | * |
||
| 539 | * Note, that the URL you pass in that list is always prepended with the current anchor |
||
| 540 | * prefix. It is not possible to specify absolute URLs there. No leading slash is required. |
||
| 541 | * |
||
| 542 | * Example: |
||
| 543 | * |
||
| 544 | * <code> |
||
| 545 | * $tmp = Array |
||
| 546 | * ( |
||
| 547 | * Array |
||
| 548 | * ( |
||
| 549 | * MIDCOM_NAV_URL => "list/{$this->_category}/{$this->_mode}/1/", |
||
| 550 | * MIDCOM_NAV_NAME => $this->_category_name, |
||
| 551 | * ), |
||
| 552 | * ); |
||
| 553 | * midcom_core_context::get()->set_custom_key('midcom.helper.nav.breadcrumb', $tmp); |
||
| 554 | * </code> |
||
| 555 | * |
||
| 556 | * @return array The computed breadcrumb data as outlined above. |
||
| 557 | * @todo Maybe cache this? I don't know how complex it really is, but DB accesses are |
||
| 558 | * already cached by the _backend core. So it is not that hard. |
||
| 559 | */ |
||
| 560 | public function get_breadcrumb_data($id = null) |
||
| 646 | |||
| 647 | /** |
||
| 648 | * Retrieve the IDs of the nodes from the URL. First value at key 0 is |
||
| 649 | * the root node ID, possible second value is the first subnode ID etc. |
||
| 650 | * Contains only visible nodes (nodes which can be loaded). |
||
| 651 | * |
||
| 652 | * @return Array The node path array. |
||
| 653 | */ |
||
| 654 | public function get_node_path($node_id = null) |
||
| 673 | |||
| 674 | /** |
||
| 675 | * Retrieve the ID of the upper node of the currently displayed node. |
||
| 676 | * |
||
| 677 | * @return mixed The ID of the node in question. |
||
| 678 | */ |
||
| 679 | public function get_current_upper_node() |
||
| 683 | } |
||
| 684 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.