We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 36552
    • 32 Posts
    In my Wayfinder submenu for "Parent A", I need to include a link for a specific child of "Parent B" and "Parent C" and I'm not quite certain the best method to do this.

    The obvious answer would be to replicate those menu items as child resources of "Parent A" and redirect them to the matching child resources of B and C.

    Is there another way, where I:
    A. don't create empty resources in my tree
    B. don't duplicate anything
    C. don't create a snippet that essentially replicates what Wayfinder is already doing so well

    Thanks for any ideas or solutions.

    This question has been answered by djad33. See the first response.

      • 20413
      • 2,877 Posts
      Would weblinks work?
        @hawproductions | http://mrhaw.com/

        Infograph: MODX Advanced Install in 7 steps:
        http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

        Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
        http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower
        • 36552
        • 32 Posts
        They would, but still result in another resource entry in the site tree. This really seems to be the most painless way though.

        Quote from: mrhaw at Jun 06, 2014, 03:21 PM
        Would weblinks work?
          • 20413
          • 2,877 Posts
            @hawproductions | http://mrhaw.com/

            Infograph: MODX Advanced Install in 7 steps:
            http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

            Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
            http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower
          • discuss.answer
            • 36552
            • 32 Posts
            I ended up creating a new Wayfinder parameter and creating a modified version of the class to handle it. Probably not the most sane solution, but it offers some flexibility going forward and might end up being useful beyond this project.

            Manager Wayfinder snippet now points to 'snippet.wayfinder.offset.php'
            Snippet includes 'wayfinder.offset.inc.php'

            New snippet param is offsetChildren. It allows for multiple "adoptive" children under a parent and multiple instances within the same Wayfinder snippet.

            offsetChildren=`parent_id|resource_id_of_child:desired_menuindex,resource_id_of_2nd_child:desired_menuindex||repeat pattern for each parent as needed


            In my particular instance:
            offsetChildren=`4|95:998,23:999`


            Use '||' to separate parent/adopted child groups.

            Extended example:
            offsetChildren=`4|95:998,23:999||6|24:800,14:801||9|95,23`


            Resources 95 and 23 each have different parents and different menuindex values for their placement in their "natural" submenus. I am now also using them in my submenu for top-level resource #4 and pushing them to the last 2 slots in that submenu.

            Without the new menuindex, they will use their original menuindex placement in the adoptive parent submenu as well.

            This was only built and tested for 2nd-level items, so I'm uncertain if a 3rd-level submenu would also replicate in its adoptive home.

            Where the work begins:
            $this->getData()


            After the query is executed, I check for the param setting in $this->_config. If it's been set, I explode the values and run through them, creating 2 new arrays.

            $this->offsetParents //contains the ids of the parents set in the param
            /*Array
            (
                [0] => 4
            )
            */
            $this->offsetChildren //contains the adoptive children [key] with parent and menuindex
            /*
            Array
            (
                [95] => Array
                    (
                        [parent] => 4
                        [menuindex] => 998
                    )
            
                [28] => Array
                    (
                        [parent] => 4
                        [menuindex] => 999
                    )
            
            )
            */ 
            


            if($this->offsetChildren)
            becomes the new test to determine if any additional code needs to be run going forward

            The next step in $this->getData() is to loop through the query results to build the data for the menu.
            //loop through the results
            for($i=0;$i<$numResults;$i++)  {
            	$new_doc = null; //NEW - prevent duplicate resource from gumming up the works
            	$tempDocInfo = $modx->db->getRow($result);
            	$resultIds[] = $tempDocInfo['id'];
            	//NEW - test for offsetChildren and duplicate $tempDocInfo and insert new values - ****
            	if($this->offsetChildren){
            		if(array_key_exists($tempDocInfo['id'],$this->offsetChildren)){
            			$new_params = $this->offsetChildren[$tempDocInfo['id']];
            			$new_doc = $tempDocInfo;
            			$new_doc['parent'] = $new_params['parent']; // set adoptive parent id
            			$new_doc['menuindex'] = $new_params['menuindex']; // set our menuindex value
            			$resultIds[] = $new_doc['id'];
            		}
            	}
            //Create the link
            


            Beyond this point, I simply parallel the tests and updates Wayfinder is already running using a test for $new_doc
            if($new_doc){
            	$this->hasChildren[] = $new_doc['parent'];
            }
            //used with each statement -- I don't know if they are all necessary, but I didn't want to break anything important
            


            At the end of $this->getData, I push each $new_doc into the $resourceArray.
            if($new_doc){
            	$resourceArray[$new_doc['level']][$new_doc['parent']][] = $new_doc;
            }
            


            Now we return to run(), where getData() is called, and add a test and array loop after ksort in order to apply our desired menuindex settings.

            function run() {
                    global $modx;
                    [...]
                    //Get all of the documents
            	$this->docs = $this->getData(); // where everything above is executed
                    if (!empty($this->docs)) {
            		//Sort documents by level for proper wrapper substitution
            		ksort($this->docs);
            			
                            //for offsetChildren
            		//we are testing for offsetChildren's existence and then reordering the submenus for the adoptive parent in order to use our assigments ****
            		if($this->offsetChildren){
            			foreach($this->docs[2] AS $k=>&$v){
            				if(in_array($k, $this->offsetParents)){
            					//you need to reorder the subs based on menuindex
            					foreach($v AS $key => $row){
            						$order[$key] = $row['menuindex'];
            					}
            					array_multisort($order, SORT_ASC, $v);
            				}
            			}
            		}
                            //BACK TO NORMAL FUNCTION
            		//build the menu
            		return $this->buildMenu();
                            [...]
            


            That's it.

            I tried to keep as light a footprint as possible. Wayfinder is a workhorse and solid and refactoring the code for better efficiency to handle this would just be foolish (for me).

            Of course, creating new resources (as weblinks) would have been much easier, but where'e the fun in that?

            I've attached the snippet and class code, if anyone's interested.
              • 20413
              • 2,877 Posts
              Wow, thanks for sharing!! Very creative way of solving it. smiley
                @hawproductions | http://mrhaw.com/

                Infograph: MODX Advanced Install in 7 steps:
                http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

                Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
                http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower
                • 36552
                • 32 Posts
                It was fun. I hope it helps someone else out sometime.