We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 22303 MODX Staff
    • 10,725 Posts
    Here’s a beta of a new version of UltimateParent I started preparing for MODx 0.9.5. Biggest new feature is that it does not query the database at all. But it requires the new $modx->getParentIds() function features only available in MODx 0.9.5 beta 1 and subsequent releases. Those of you beta testing give it a try and let me know what you think. Thanks to Susan Ottwell for the original snippet design/code.

    Thanks also to staed for the topLevel parameter addition, which I’ve incorporated here in a slightly different form.

    @staed, let me know if this meets the requirements you were addressing with your mod at http://modxcms.com/forums/index.php/topic,5555.msg51597.html#msg51597.

    <?php
    /**
     * @name UltimateParent
     * @version 2.0 beta (requires MODx 0.9.5+)
     * @author Jason Coward <[email protected]>
     * 
     * @param &id The id of the document whose parent you want to find.
     * @param &top The top node for the search.
     * @param &topLevel The top level node for the search (root = level 1)
     * 
     * @license Public Domain, use as you like.
     * 
     * @example [[UltimateParent? &id=`45` &top=`6`]] 
     * Will find the ultimate parent of document 45 if it is a child of document 6;
     * otherwise it will return 45.
     * 
     * @example [[UltimateParent? &topLevel=`2`]]
     * Will find the ultimate parent of the current document at a depth of 2 levels
     * in the document hierarchy, with the root level being level 1.
     * 
     * This snippet travels up the document tree from a specified document and
     * returns the "ultimate" parent.  Version 2.0 was rewritten to use the new
     * getParentIds function features available only in MODx 0.9.5 or later.
     * 
     * Based on the original UltimateParent 1.x snippet by Susan Ottwell
     * <[email protected]>.  The topLevel parameter was introduced by staed and
     * adopted here.
     */
    $top= isset ($top) && intval($top) ? $top : 0;
    $id= isset ($id) && intval($id) ? intval($id) : $modx->documentIdentifier;
    $topLevel= isset ($topLevel) && intval($topLevel) ? intval($topLevel) : 0;
    if ($id && $id != $top) {
        $pid= $id;
        if (!$topLevel || count($modx->getParentIds($id)) >= $topLevel) {
            while ($parentIds= $modx->getParentIds($id, 1)) {
                $pid= array_pop($parentIds);
                if ($pid == $top) {
                    break;
                }
                $id= $pid;
                if ($topLevel && count($modx->getParentIds($id)) < $topLevel) {
                    break;
                }
            }
        }
    }
    return $id;
    ?>
      • 6726
      • 7,075 Posts
      Very nice Jason, I’ll give this a look and replace the older version of UltimateParent I have running on one of my 0.9.5 upgraded website with the new one to see how that works smiley
        .: COO - Commerce Guys - Community Driven Innovation :.


        MODx est l&#39;outil id
        • 28042 ☆ A M B ☆
        • 24,524 Posts
        Wonderful! I love seeing others take the skeletons I toss out and actually make something useful out of them.
          Studying MODX in the desert - http://sottwell.com
          Tips and Tricks from the MODX Forums and Slack Channels - http://modxcookbook.com
          Join the Slack Community - http://modx.org
          • 22303 MODX Staff
          • 10,725 Posts
          Just curious, did anyone ever confirm that this worked as a suitable replacement for the existing UltimateParent in the 0.9.5 beta releases?
            • 29076
            • 615 Posts
            Sorry, but I’m not shure what kind of feeback you really want (I’m not a developer), but I tested it with the new code, and it works. Fast. (My call: [!Wayfinder? &startId=`[[UltimateParent]]` !] , replaced the old Ultimateparent-code with the code above. MODx 0.9.5 stable ).

            Anyway, thanks for your work in making MODx even better. And better. And better.
              I think, thererfor I am! But what I am, and why...?
              • 6726
              • 7,075 Posts
              Yes Jason I do confirm this is a suitable replacement I use it on several 0.9.5 website and it’s working great !
              FYI, I am running PHP 5.1.6 with MODx 0.9.5 RC3 rev 2066.
                .: COO - Commerce Guys - Community Driven Innovation :.


                MODx est l&#39;outil id
                • 28338
                • 46 Posts
                Quote from: OpenGeek at Sep 21, 2006, 10:10 PM

                @staed, let me know if this meets the requirements you were addressing with your mod

                Sorry for the late reply, but that seems to be it! Thanks. A lot cleaner than my code smiley
                  • 30223
                  • 1,010 Posts
                  May I suggest another parameter which works opposite of &topLevel? i.e. working a max number of levels backwards? In a deeply nested structure this could be quite handy I imagine... Don’t know what you would call the parameter though... &maxLevels might be confusing as it’s used in other snippets. ’stepBack’ perhaps?
                    • 30223
                    • 1,010 Posts
                    I’ve just started playing with this to see if I could implement a "stepBack" when I noticed that ultimate when using the &topLevel parameter means "as long as its less then 10 levels deep" due to the default limit in getParentIds. Now I know it’s not particularly practical to make data/document structures 10 levels deep but is there any reason to put this limit on UltimateParent? With a small change to the code this can be changed.

                    <?php
                    $top= isset ($top) && intval($top) ? $top : 0;
                    $id= isset ($id) && intval($id) ? intval($id) : $modx->documentIdentifier;
                    $topLevel= isset ($topLevel) && intval($topLevel) ? intval($topLevel) : 0;
                    //mod - adjust getParentIds parameter if topLevel > 10
                    $height = max($topLevel,10);
                    //
                    if ($id && $id != $top) {
                        $pid= $id;
                        if (!$topLevel || count($modx->getParentIds($id,$height)) >= $topLevel) { //added 2nd param
                            while ($parentIds= $modx->getParentIds($id, 1)) {
                                $pid= array_pop($parentIds);
                                if ($pid == $top) {
                                    break;
                                }
                                $id= $pid;
                                if ($topLevel && count($modx->getParentIds($id,$height)) < $topLevel) { //added 2nd param
                                    break;
                                }
                            }
                        }
                    }
                    return $id;
                    ?>
                    
                      • 22563
                      • 63 Posts
                      Hi,

                      first thanks for this nice snippet!

                      But I have a light problem realizing my menu structure with it:

                      I am trying to create 3 level menu with three blocks and have problems with &topLevel :

                      A B C <- horizontal menu
                      C1 C2 C3 <- horizontal sub menu

                      C2a <- verstical 2. sub menu
                      C2b

                      for A, B, C I have
                      [!Wayfinder?startId=`0` &hereClass=`current` &level=`1` &outerClass=`mainnav`!]


                      for C1, C2, C3 I have
                      [!Wayfinder? &startId=`[[UltimateParent?]]` &level=`1` &hideSubMenus=`1` &hereClass=`current` &outerClass=`submenu` !]


                      for C2a, C2b I have
                      [!Wayfinder? &startId=`[[UltimateParent?  &topLevel=`2`]]` &hideSubMenus=`1` &hereClass=`current` &outerClass=`submenu2` !]


                      I only want C2a, C2b to appear if I select C2 or C2a, C2b
                      But with the wayfinder code above the folowing happens:
                      If I select C -> C1, C2, C3 appear in the second sub menu box. But this should be empty!

                      Any help on this would be greate. Thanks!
                      padexx