We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 19328
    • 433 Posts
    Hi, I wrote a plugin to check if a page has got a certain template, and if so, remove it from the friendly alias path by setting uri_override to 1 and changing it with a plugin.
    I thought I'd just post it here for anyone interested and to get feedback on the code. I'm not good at programming so it can probably be done much better/faster etc. Maybe my attempt will give someone some ideas on how to do this better ;-)

    In this plugin the template is checked up to five parents. It is set to the OnBeforeDocFormSave event.

    <?php
    /* fiveUp/fourUp/threeUp/twoUp/oneUp/self */
    
    /* get parent template (one up) */
    $oneUp= $resource->get('parent');
    if ($oneUp != '') {
      $oneUpObject = $modx->getObject('modResource',$oneUp);
      $templateOneUp = $oneUpObject->get('template');
      $aliasOneUp = $oneUpObject->get('alias');
      
      /* get grandparent  (two up) */
      $twoUp = $oneUpObject->get('parent');
      
      if ($twoUp !='') {
        $twoUpObject = $modx->getObject('modResource',$twoUp);
        $templateTwoUp = $twoUpObject->get('template');
        $aliasTwoUp = $twoUpObject->get('alias');
        
        /* get greatgrandparent (three up) */
        $threeUp = $twoUpObject->get('parent');
        
        if ($threeUp !='') {
          $threeUpObject = $modx->getObject('modResource',$threeUp);
          $templateThreeUp = $threeUpObject->get('template');
          $aliasThreeUp = $threeUpObject->get('alias');
          
          /* get ubergrandparent  (four up) */
          $fourUp = $threeUpObject->get('parent');
          
          if ($fourUp !='') {
    	$fourUpObject = $modx->getObject('modResource',$fourUp);
    	$templateFourUp = $fourUpObject->get('template');
    	$aliasFourUp = $fourUpObject->get('alias');
    	
    	/* get five up */
    	$fiveUp = $fourUpObject->get('parent');
    	if ($fiveUp !='') {
    	  $fiveUpObject = $modx->getObject('modResource',$fiveUp);
    	  $templateFiveUp = $fourUpObject->get('template');
    	  $aliasFiveUp = $fiveUpObject->get('alias');
    	  $last = 'fiveUp';
    	
    	} else { $last = 'fourUp'; }	// no fiveup
          } else { $last = 'threeUp'; } // no fourup
        } else { $last = 'twoUp'; } // no threeup
      } else { $last = 'oneUp'; } // no twoup
    } else { $last = 'self'; } // no oneup
    
    // default
    $newAliasOneUp = '';
    $newAliasTwoUp = '';
    $newAliasThreeUp = '';
    $newAliasFourUp = '';
    $newAliasFiveUp = '';
    
    // create the aliases with slash if they exist
    switch ($last)
    {
        	case 'oneUp': 	$newAliasOneUp = $aliasOneUp.'/';
        	break;
    	case 'twoUp': 	$newAliasOneUp = $aliasOneUp.'/'; 
      			$newAliasTwoUp = $aliasTwoUp.'/';
        	break;
    	case 'threeUp': $newAliasOneUp = $aliasOneUp.'/'; 
      			$newAliasTwoUp = $aliasTwoUp.'/';
      			$newAliasThreeUp = $aliasThreeUp.'/';
        	break;
    	case 'fourUp': 	$newAliasOneUp = $aliasOneUp.'/'; 
      			$newAliasTwoUp = $aliasTwoUp.'/';
        			$newAliasThreeUp = $aliasThreeUp.'/';
      			$newAliasFourUp = $aliasFourUp.'/';
        	break;
    	case 'fiveUp': 	$newAliasOneUp = $aliasOneUp.'/'; 
      			$newAliasTwoUp = $aliasTwoUp.'/';
          			$newAliasThreeUp = $aliasThreeUp.'/';
      			$newAliasFourUp = $aliasFourUp.'/';
      			$newAliasFiveUp = $aliasFiveUp.'/';
        	break;
    }
    
    // if one of the parents has the hidden template (5), change the alias to nothing
    if ($templateOneUp == '5') 	{ $newAliasOneUp = ''; }
    if ($templateTwoUp == '5') 	{ $newAliasTwoUp = ''; }
    if ($templateThreeUp == '5') 	{ $newAliasThreeUp = ''; }
    if ($templateFourUp == '5') 	{ $newAliasFourUp = ''; }
    if ($templateFiveUp == '5') 	{ $newAliasFiveUp = ''; }
    
    $alias = $resource->get('alias');         
    $newUri = $newAliasFiveUp.$newAliasFourUp.$newAliasThreeUp.$newAliasTwoUp.$newAliasOneUp.$alias;
    $resource->set('uri_override', '1');     
    $resource->set('uri', $newUri);
    $resource->save();
      • 34012
      • 88 Posts
      Hi Michelle,

      MODX has getParentIds function so you dont need to manually go fetching each parent of the resource. On save the id of saved resource is bit tough to get on first save but here is a quick snippet that should (not proven in practice) do the same as yours does.

      <?php
      $e = $modx->Event;
      $resourceId = $e->params['id']; // Get the ID of resource
      
      $q = $modx->newQuery('modResource'); // Fetch the parents
      $q->where(array('id:IN' => $modx->getParentIds($resourceId, 10, 'web'))); /* 10 = depth, 'web' = context */
      $parents = $modx->getCollection('modResource', $q);
      
      foreach($parents as $parent) {
          if ($parent->get('template') != 5) { // If not the hidden template
              $out[] = $parent->get('alias');
          }
      }
      $newUri = implode('/', $out) . "/" . $resource->get('alias');
      $resource->set('uri_override', '1');     
      $resource->set('uri', $newUri);
      $resource->save();
      


      Got motivated from your idea as your idea does cut few corners with clients managing the URL's smiley [ed. note: lazylegs last edited this post 12 years, 5 months ago.]
        Almost retired from web-development industry but still randomly writing at Lazylegs.info and on schedule hopefully in near future to finish Oracle and PostgreSQL ports of MODX
        • 19328
        • 433 Posts
        Wow, so much shorter!! Thanks!
        I'm going to test it right away!
          • 3749
          • 24,544 Posts
          Let me suggest a slightly different version. You shouldn't need a pointer to the event because the $resource variable should be set for you, and you might want to skip the process when the resource is being updated (once they're all set):

          <?php
          
          if ($mode != modSystemEvent::MODE_NEW) {
              return '';
          }
          
          $q = $modx->newQuery('modResource'); // Fetch the parents
          $q->where(array('id:IN' => $modx->getParentIds($resource->get('id']), 10, 'web'))); /* 10 = depth, 'web' = context */
          $parents = $modx->getCollection('modResource', $q);
          
          foreach($parents as $parent) {
              if ($parent->get('template') != 5) { // If not the hidden template
                  $out[] = $parent->get('alias');
              }
          }
          $newUri = implode('/', $out) . "/" . $resource->get('alias');
          $resource->set('uri_override', '1');     
          $resource->set('uri', $newUri);
          $resource->save();
          



            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
            • 34012
            • 88 Posts
            Need to test this tomorrow.

            On the plugin event, new resource has id = 0 thats why the pointer to event is used. But last time I've used onDocFormSave or onBeforeDocFormSave was around have 2.1 or even earlier. So could have changed to that you can use $resource->get('id') nowadays. If not, should throw error to log of undefined method on object if recal right.
              Almost retired from web-development industry but still randomly writing at Lazylegs.info and on schedule hopefully in near future to finish Oracle and PostgreSQL ports of MODX
              • 3749
              • 24,544 Posts
              Yes, I think you may be right about that. I'm not sure your method will work either, since the resource doesn't actually have an ID at that point.

              It might be necessary to connect the plugin to OnDocFormSave, where I think the resource ID will be set.
                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
                • 34012
                • 88 Posts
                Did few tests,

                Yes, both options to get resource id actually do work. So pointer to Event is not necessary and $resource->get('id') is fine.

                Need to install 2.2 to see if this plugin might actually work. On 2.1.3 that I got it is impossible to use getParentIds on onDocFormSave or onBeforeDocForm save as the methods fetches the context's map and goes through parents there.. The new object is not yet saved in to context map so this solution does not work on first save.

                There was also a "bug" in there, the options ('web') needs to be array('context' => 'web'); Need to investigate more, good idea but should have tested in practice before opening my mouth. Did some tests inside snippet before the first post.
                  Almost retired from web-development industry but still randomly writing at Lazylegs.info and on schedule hopefully in near future to finish Oracle and PostgreSQL ports of MODX
                  • 34012
                  • 88 Posts
                  Away from computer does help sometimes, went away to watch TV and got the idea how to get this to work. As the map is not build for that resource, it is still build for the parent so lets fetch that resource's parents and include it back for query

                  <?php
                  $tempParent = $resource->get('parent'); //"cache" the parent
                  
                  $tempParents = $modx->getParentIds($tempParent, 10, array('context' => 'web')); // depth = 10 and context = web
                  $tempParents[] = $tempParent; // Include the parent into array()
                  
                  $q = $modx->newQuery('modResource'); // Fetch the parents
                  $q->where(array('id:IN' => $tempParents)); 
                  $parents = $modx->getCollection('modResource', $q);
                   
                  foreach($parents as $parent) {
                      if ($parent->get('template') != 5) { // If not the hidden template
                          $out[] = $parent->get('alias');
                      }
                  }
                  $newUri = implode('/', $out) . "/" . $resource->get('alias'); // If you want, add . ".html" in to end
                  $resource->set('uri_override', '1');     
                  $resource->set('uri', $newUri);
                  $resource->save();


                  That will for example output /grandparent/parent/page <-- so note that the uri does not have .html, that needs to be added to end if you want.

                  I left out the Bob's good idea to do this only on new resource. As lets say user makes mistake on pagetitle, alias is also bonkers and then the uri would be bonkers too. So changing the pagetitle and alias is not enough. Also the frozen uri needs to be changed by hand then.

                  But that was just my own judgement for it smiley [ed. note: lazylegs last edited this post 12 years, 5 months ago.]
                    Almost retired from web-development industry but still randomly writing at Lazylegs.info and on schedule hopefully in near future to finish Oracle and PostgreSQL ports of MODX