We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26503
    • 620 Posts
    I'm trying to build a custom navigation tree in an array so I can hand it off to a mobile device app, I found a great little API function "getTree" which returns the site structure in a multi-dimensional array. Perfect, just what I am looking for.

    HOWEVER

    all it returns is an array of resource ids, how can I add things like, menutitle, published, hidden etc to that array?
      *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

      Sean Kimball CLP, CLS.
      Technical Director / Sr. Developer | BigBlock Studios
      ._______________________________________________.
      Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
      27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
      phone/fax: 905-426-5525
      • 3749
      • 24,544 Posts
      If the tree were one-dimensional (as you get from getChildIds) something like the code below would work -- just iterating through them, getting each doc, and using a Tpl chunk to format the output. Since getTree() is recursive, you're going to get back a multi-dimensional array. You'll need to iterate through it with something more complicated than a simple foreach, but the chunk and the code to get each resource, its fields, and the chunk will be the same. Hope that makes sense.

      I would try the code below with $idArray = $modx->getChildIds(0); as the first line. Once you like the output, you can look at traversing the tree returned by getTree().

      $idArray = getTree( . . .);
      
      foreach $idArray as $docId {
      
          $doc = $modx->getObject('modResource', $docId);
          if ($doc) {
              $fields = $doc->toArray();
              $output .= $modx->getChunk('TreeTpl', $fields);
          }
      }
      
      return $output;
      


      TreeTpl chunk (note: If snippet must be installed):

      <p>Page Title: [[+pagetitle]]</p>
      <p>Menu Title: [[+menutitle]]</p>
      <p>Published: [[If?
         &subject=`[[+published]]`
         &operator=`EQ`
         &operand=`1`
         &then=`Yes`
         &else=`No`
      ]]</p>
      <p>Hidden: [[If?
         &subject=`[[+hidemenu]]`
         &operator=`EQ`
         &operand=`1`
         &then=`Yes`
         &else=`No`
      ]]</p>
      



      Note that the method above is very inefficient since it could make many queries to the DB. OTOH, if the resources are cached, it may be fast enough. If not, you'd have to come up with a more efficient query that got multiple resources at once. It occurred to me that it might be faster to get *all* the resources with getCollection() or getIterator() and traverse the objects, organizing the tree yourself using the 'parent' field.

      $c = array(
          'deleted' => '0',
          'published' => '1',
          'hidemenu' => '0',
      );
      
      $docs = $modx->getCollection('modResource', $c);
      /* or */
      $docs = $modx->getIterator('modResource', $c); 
        Did I help you? Buy me a beer
        Get my Book: MODX:The Official Guide
        MODX info for everyone: http://bobsguides.com/modx.html
        My MODX Extras
        Bob's Guides is now hosted at A2 MODX Hosting
        • 4172
        • 5,888 Posts
        how would you like to have your output?

        There are different ways to prepare custom-trees with help of bloX
          -------------------------------

          you can buy me a beer, if you like MIGX

          http://webcmsolutions.de/migx.html

          Thanks!
          • 26503
          • 620 Posts
          @bruno - the output will be a json encoded array & I can't 'rely' on any modx extras being installed.

          @bob - luckily we are not formatting anything at all, just handing some json off to the mobile device - so I'm trying to balance how much data is passed [bandwidth] and how much massaging it needs on the modx end [save processing on the client end]

          getCollection was way too slow & would have been a huge chunk of data to push. [there are about 3000 resources]

          I would up going with something like this for now
          	function getResourceTree(){
          		
          		$resourceTree = array();
          		
          		$results = $this->modx->query(
          			"SELECT id,parent,published,menuindex,menutitle FROM modx_site_content where published = '1' and hidemenu = '0'"
          			);
          		
          		while ($record = $results->fetch(PDO::FETCH_ASSOC)) {
          		    
          		    $resourceTree[] = $record;
          		}
          		
          		return $resourceTree ? $resourceTree : '';
          
          	}


          Which of course does not organize the tree at all, and as you suggested I will have to whip through it & organize by id/parentid etc as I will have to check permissions on the individual resources *sigh*
          I was just hoping there was another API tool that might give me more to work with than getTree

          [Speaking of permissions ~before I start a new thread~ any idea on how to create & grant a user a session VIA the API? wink]


          Anyway, here is where I started with recursing through the getTree output. Oh, it's messy, and it doesn't really work right now, but you get the idea I was after:

          // similar to what getTree outputs
          $orgarray = array(
          	'101' => '101',
          	'102' => '102',
          	'103' => '103',
          	'104' => array(
          		'201' => '201',
          		'202' => '202',
          		'203' => array(
          			'301' => '301',
          			'302' => array(
          				'401' => '401',
          				'402' => '402',
          					'501' => array(
          					'502' => '502',
          					'503' => '503',
          					'504' => '504',
          					'505' => 'special',
          					'506' => '506'
          					),
          				),
          			),
          		),
          	'105' => '105',
          	'106' => '106',
          	'107' => '107');
          	
          	
          //$orgarray = $modx->getTree(0,3);
          
          function getpath($array, $needle, $stack = array()){
          	foreach($array as $key => $value) {
          		if(is_array($value)){
          			array_push($stack, $key);
          			return getpath($value, $needle, $stack);
          		}
          		if($value == $needle){
          			array_push($stack, $key);
          			return '['.implode('][', $stack).']';	
          		}
          	}	
          	return false;
          }
          
          function recursearray($array, &$newarray){
          	
          	foreach($array as $key => $value){
          		
          		echo getpath($orgarray, $value);
          					
          		if (is_array($value)){
          
          			recursearray($value, &$newarray);
          			// add keys id, menutitle to array			
          			
          		}else{
          			
          			$thiskey = getpath($orgarray, $value);
          			echo $thiskey;
          			// change the value [add array]
          			$thiskey = 'new-value';
          			
          		}
          	
          	} 
          	
          	return $array;
          	
          }
          
          recursearray($orgarray, $newarray);
          
          echo '<pre>';
          print_r($newarray);
          echo '</pre>';
          
          
          
            *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

            Sean Kimball CLP, CLS.
            Technical Director / Sr. Developer | BigBlock Studios
            ._______________________________________________.
            Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
            27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
            phone/fax: 905-426-5525
            • 3749
            • 24,544 Posts
            It looks like a good start. smiley

            If I'm understanding your question about sessions, you want something like this:

            $userName = 'whatever';
            
            $contexts = array(
                'web',
                'manager'
            );
            
            /* Create user with $modx->newObject() here 
               and set username */
            
            /* set MODX current user */
            $usr = $modx->getObject('modUser', array('username' => $username));  /* or grab the ID and use that */
            $modx->user =& $usr;
            $modx->getUser();
            
            /* log the user in */
            foreach ($contexts as $ctx) {
                $modx->user->addSessionContext($ctx);
            }
            

              Did I help you? Buy me a beer
              Get my Book: MODX:The Official Guide
              MODX info for everyone: http://bobsguides.com/modx.html
              My MODX Extras
              Bob's Guides is now hosted at A2 MODX Hosting
              • 26503
              • 620 Posts
              Quote from: BobRay at Feb 17, 2013, 04:05 PM
              It looks like a good start. smiley

              If I'm understanding your question about sessions, you want something like this:

              $userName = 'whatever';
              
              $contexts = array(
                  'web',
                  'manager'
              );
              
              /* Create user with $modx->newObject() here 
                 and set username */
              
              /* set MODX current user */
              $usr = $modx->getObject('modUser', array('username' => $username));  /* or grab the ID and use that */
              $modx->user =& $usr;
              $modx->getUser();
              
              /* log the user in */
              foreach ($contexts as $ctx) {
                  $modx->user->addSessionContext($ctx);
              }
              



              That will generate and hand off the client side cookie[s]? All I have to do then is check the cookie/access against the resource to see if they have access? Jeez, modx sure can make life easy eh?
                *** Not just websites, we also create signage, banners, print, trade show displays and more! ***

                Sean Kimball CLP, CLS.
                Technical Director / Sr. Developer | BigBlock Studios
                ._______________________________________________.
                Bigblock Studios http://www.bigblockstudios.ca Web site design & development.
                27-1300 King Street East. Box 167 Oshawa, Ontario L1H8J4 Canada.
                phone/fax: 905-426-5525
                • 3749
                • 24,544 Posts
                It may or may not involve client-side cookies -- that's under the hood.

                All you need to do to tell if a user is logged in is this:

                if ($modx->user->hasSessionContext($modx->context->get('key)) {
                    /* user is logged in to current context */
                }


                If you want to check what the user can do in general:

                if ($modx->user->hasPermission('some_permission')) {
                    }


                To check whether they have the right to do something with the current resource:
                 if ($modx->resource->checkPolicy('save')) {
                    }


                To check group membership:

                  if ($modx->user->isMember('some_user_group')) {
                  }
                  Did I help you? Buy me a beer
                  Get my Book: MODX:The Official Guide
                  MODX info for everyone: http://bobsguides.com/modx.html
                  My MODX Extras
                  Bob's Guides is now hosted at A2 MODX Hosting