Overriding router.php

1,450 views
Skip to first unread message

Nils Rückmann

unread,
Apr 1, 2012, 4:12:33 PM4/1/12
to joomla-...@googlegroups.com
Hi,

what do you see as "best practise" for overriding core routers ?

and in this case: shouldn't we add the ability to override it natively ?

NR

Hannes Papenberg

unread,
Apr 1, 2012, 5:12:36 PM4/1/12
to joomla-...@googlegroups.com

Please take a look at the thread named "Routing JApplicationWeb" on the platform mailinglist. The proposed code allows among other things exactly that. Right now its not possible to override a core roter without overriding the complete JRouter class. The proposed code would only include the core router if it isnt loaded already.

--
You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-cms/-/syzmhRxhPk0J.
To post to this group, send an email to joomla-...@googlegroups.com.
To unsubscribe from this group, send email to joomla-dev-cm...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/joomla-dev-cms?hl=en-GB.

Nils Rückmann

unread,
Apr 1, 2012, 6:00:43 PM4/1/12
to joomla-...@googlegroups.com
Thanks Hannes, i know your router ;) I don't see any progress on it (or the cms as well) so i ask for current solutions.

But that's a general problem i think. The plattform is new, interesting, something to play with .. all people want to enhance it and the cms can be lucky if it's only a few steps behind, because of the "screw the cms, they have to look theirself"-mentality.

Okay now it's off-topic, but who cares ...

Hannes Papenberg

unread,
Apr 1, 2012, 6:08:02 PM4/1/12
to joomla-...@googlegroups.com

So far the router has been mostly ignored by the people in charge. I'm more than happy to invest more time into this and bring everything up to speed if I get a positive feedback along the line of "The concept looks good, we want to see that in the platform/cms. However, your actual implementation sucks." That is something that I can work with. Right now I didn't get any feedback at all about this.

--
You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-cms/-/EYPRblAVmywJ.

Amy Stephen

unread,
Apr 1, 2012, 8:50:35 PM4/1/12
to joomla-...@googlegroups.com
Nils -

If you are looking for a system plugin that you can use as a model for overriding core functionality, I added one to my personal github repository a couple of weeks ago.

https://github.com/AmyStephen/Layout-Override-Plugin

It fires off for the onAfterInitialise -- which is before the routing event -- so it's the ideal time to use methods like JFactory::getURI() to retrieve the extract HTTP request, and then pass it into the parse method.

https://github.com/joomla/joomla-platform/blob/staging/libraries/joomla/environment/uri.php

That's sketchy comments and I'm not certain exactly what you are looking for, if it's a solution? (In which case if the Joomla URLs aren't to your liking, an extension is the best immediate bet.)

Or, if you want to code a simple solution, in which case, this plugin and follow up questions might be a good bet.

In general, for any custom website I build, I like to create a real simple override to get rid of those gnarly primary keys and build the patterns I want. If you learn how to do exactly what you are saying -- override the core routing -- you can get that done pretty easily.

One comment on the CMS thing - IMO - the big solutions for the Joomla CMS will emerge out of the platform. I've been a critic of some of Joomla's development approaches, but I believe they are now on the right track. It might take awhile for those benefits to start showing in the CMS, but when they do, it'll be much more revolutionary than incremental. Anyway, that's just my opinion.

Hope the plugin helps.
Amy


Gary Mort

unread,
Apr 8, 2012, 2:22:27 PM4/8/12
to joomla-...@googlegroups.com
In what manner do you wish to override it and what version of Joomla?  Assuming 2.5+, interestingly, JRoute has a lot of powerful, but unused, functionality already.

Take parsing a URL, for example:

Starting on line 36, we have the call to $app->route();
So that is a call to libraries\joomla\application\application.php
        $uri = clone JURI::getInstance();

        $router = $this->getRouter();
        $result = $router->parse($uri);

        JRequest::set($result, 'get', false);

        // Trigger the onAfterRoute event.
        JPluginHelper::importPlugin('system');
        $this->triggerEvent('onAfterRoute');


This gives you TWO ways of overriding it.  First off, you can have a system plugin running at onAfterRoute where you can go ahead and implement your own special logic, and if you want to override the calculation, create your own $result array and call JRequest::set($overrideResult, 'get', true) where true is to override existing values. 

Secondly, you can ovveride things in JRouter::parse
libraries\joomla\application\router.php

Note: first JRouterSite will do some formatting on the uri, it then passes that uri to parse in the parent class JRouter
JRouter will FIRST call $this->_processParseRules($uri)

It will then take the uri and pass it through the parse functions. 

You can therefore define your own function which will take the uri and manipulate it under some circumstances.

You can change the uri into something else that you know will be processed the way you want using a system plugin as Amy suggested:
ie:
class plgSystemMyRouter extends JPlugin {

    public function onAfterInitialize()
    {
       global $app;
    // you could also use $app = JFactory::getApplication('site');

    // get the router
    $router = $app->getRouter();

    // add my own rules
    // create a callback array to call the interchangeable method of this object
    $myrouterCallback = array($this, 'interchangeable');
    // attach the callback to the router
    $router->attachBuildRule($myRouterCallback);

    }
/**
     * @param   JRouterSite &$router  The Joomla Site Router
     * @param   JURI  &$uri  The URI to parse
     *
     * @return  array  $vars The array of processed URI variables
*/
    public function interchangeable($router, $uri)
    {

      $vars = array();

    // check the $uri object and set/override some of the variables
      return $vars;
    }

}


If for some reason merely changing the vars is not sufficient for you, since you have the router AND the uri objects, you can get around that as well:
define('PLGSYSTEMMYROUTER_MODE_SKIP_SEF', 2);
define('PLGSYSTEMMYROUTER_MODE_SKIP_RAW', -1);
/**
     * @param   JRouterSite &$router  The Joomla Site Router
     * @param   JURI  &$uri  The URI to parse
     *
     * @return  array  $vars The array of processed URI variables
*/
    public function changeRouteURI($router, $uri)
    {    
     $skipProcessing = false;
     $vars = array();
    
    // if the uri has the variable I use to do my own thing, do it!
    if $uri->getVar('myTriggerVariable',false) {
        // maybe we only want to skip under some specific condition
        // assuming always skip
        $skipProcessing = true;
        // make my uri changes
        $uri-setVar('someNewVariable','myValue');
        $vars['someRouteVar'] = 'someValue'       
    }
   
    // we can change how Joomla processes this URL
    if ($skipProcessing) {

    //$router->setMode(JROUTER_MODE_RAW);
    // if the router mode is RAW - integer 0, then _parseRawRoute will be called by JRouter

    //$router->setMode(JROUTER_MODE_SEF);
    // if the router mode is SEF - integer 1, then _parseSEFRoute will be called by JRouter

    // if we set it to something which is NOT SEF or RAW, nothing is done to it
    // false or null would be a logical choice,
    //but since the comparison is == not === false, null and 0/RAW are the same
    // therefore we defined our own constants.
    // SEF/RAW is a binary condition of either a positive integer or not a positive integer[0]
    // so we extend that so SKIP_SEF becomes 2 so the if clause will fail, but anything else
    // counting on checking for if mode > 0 will work
    // and SKIP_RAW is -1, so anything counting on checking mode <=0 will work
    // if it is not 0 or 1, then we don't change it because something else
    // already triggered the skip.
    $mode = $router-getMode();
    if ($mode == JROUTER_MODE_RAW) {
        $router->setMode(PLGSYSTEMMYROUTER_MODE_SKIP_RAW);
    }
    if ($mode == JROUTER_MODE_SEF) {
        $router->setMode(PLGSYSTEMMYROUTER_MODE_SKIP_SEF);
    }
  
    }

      // return our custom variables
      return $vars;
    }


In short, there is a LOT of functionality already built into Joomla that is not used... the more I dig, the more I find can be worked with instead of worked around.

-Gary








elin

unread,
Apr 9, 2012, 6:59:31 AM4/9/12
to joomla-...@googlegroups.com
Gary,

Would you want to write that up for the wiki?

Elin

Hannes Papenberg

unread,
Apr 9, 2012, 7:43:24 AM4/9/12
to joomla-...@googlegroups.com

That indeed allows you a little bit of flexibility, but you still can't switch off the menu system or override just one component router. Without having the code in front of me and relying on your statement that the parserules array is executed first, you'd have to replicate the whole menu item detection logic before you even know if the URL is for the component that you want to modify. If the rules would be run after the hardcoded behavior, you wouldn't be able to prevent the core routers from being executed first.

Fact is, that I have to write a lot of code to achieve even minor changes to the routing system.

The HP router plugin that I wrote for 1.5 is one fugly piece of code, but its the only way to achieve something like that simple thing in the current environment.

--
You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.

Gary Mort

unread,
Apr 9, 2012, 1:39:52 PM4/9/12
to joomla-...@googlegroups.com
On 4/9/2012 6:59 AM, elin wrote:
> Gary,
>
> Would you want to write that up for the wiki?

That's my problem... I can't quite get from all this raw code to
something intelligible for a wiki. I'm more than happy if anyone wants
to take it and clean it up..or post it to the wiki as is.

[Erm, that's my OTHER problem, I hate wiki interfaces and just can't
figure them out. Right now I'm learning ONE wiki interface, Githubs,
and if I accomplish that I'll be happy...dunno why, just some sort of
mental block].

Gary Mort

unread,
Apr 9, 2012, 2:43:27 PM4/9/12
to joomla-...@googlegroups.com
On 4/9/2012 7:43 AM, Hannes Papenberg wrote:

That indeed allows you a little bit of flexibility, but you still can't switch off the menu system or override just one component router. Without having the code in front of me and relying on your statement that the parserules array is executed first, you'd have to replicate the whole menu item detection logic before you even know if the URL is for the component that you want to modify. If the rules would be run after the hardcoded behavior, you wouldn't be able to prevent the core routers from being executed first.

Fact is, that I have to write a lot of code to achieve even minor changes to the routing system.


I've been doing quite a bit of that.  Writing a bunch of code to work around some deficiency.  Then afterwards having these "eureka" moments of "so that is what that method is for" and realizing many of my perceived "shortcomings" of the current platform are more shortcomings of my own understanding[and of course documentation]..  For this case, I think it takes about 30 lines of code to accomplish your goal...plus whatever custom code you need.

I'm slowly building up coding notes on these different sections so I stop rolling my own code.  In addition to slowly figuring out a decent project file structure which maximizes the strength of my IDE[PHPSTORM] and Github.  Even went ahead and upgraded my account so I can keep private code up there[as it makes it incredibly easy if it's all on github to keep joomla/Joomla-Platform and joomla/Joomla-CMS as read only submodules in a separate folder so I can reference them - including pulling the latest Dev copies of each so if there is a change which addresses my own needs, I can pull it in temporarily until the release catches up with the repository.

In this case, it's real easy to override without duplicating code.  Just think about what parseRoute actually accomplishes.

parseRoute does 3 things:
1) it calculates a set of get/post/request query variables in the format of an key=>value array
2) it sets it's own internal query variable array to the values it has parsed
3) it returns those values to whoever called it

Now, what is your goal? Well, you want to be able to set a different set of query variables and make sure their saved to the default router.  But only sometimes based on menu item...which JRouter itself will figure out for you, but by the time it does you can't make changes..... 

JRouter is a 'singleton'...this means that in theory there is only one JRouter.  Theory and the real world differ. 
'Singleton', unless someone has gone to the trouble of locking you out by placing getInstance inside the constructor, is just a suggestion - it's not a hard and fast rule!  Joomla! has not gone to that extreme.

So you can clone the current JRouter.[I lied.  As long as your using most versions of PHP 5.2 and all 5.3+ even if someone stuck getInstance in the constructor all is not lost - as long as they didn't add a magic __clone method to lock you out!  But if you want to make your code compatible with older versions of PHP[YUCK!], then you can use new instead of clone.
Remove your special processing rule from the clone. 
Use the clone to figure out the vars array and menu item
Check the menu item for your override
If it matches, change the parameter array as you wanted
Set the REAL router to skip processing
Return the array

An example, assuming your looking for menu item number 67 [It's an example!  Of course your going to do something smarter...right?]

define('PLGSYSTEMMYROUTER_MODE_SKIP_SEF', 2);
define('PLGSYSTEMMYROUTER_MODE_SKIP_RAW', -1);


    public function onAfterInitialize()
    {
       global $app;
    // you could also use $app = JFactory::getApplication('site');

    // get the router
    $router = $app->getRouter();

    // add my own rules
    // create a callback array to call the interchangeable method of this object
    $myrouterCallback = array($this, 'overrideRouterForMenu');

    // attach the callback to the router
    $router->attachBuildRule($myRouterCallback);

    }



/**
     * @param   JRouterSite &$router  The Joomla Site Router
     * @param   JURI  &$uri  The URI to parse
     *
     * @return  array  $vars The array of processed URI variables
*/
    public function overrideRouterForMenu($router, $uri)
    {    
    
     $vars = array();

      global $app;
    // you could also use $app = JFactory::getApplication('site');

    // get the true router
    $trueRouter= $app->getRouter()

// to avoid a recursion trap, we need to make sure that only
// the true router can call us!  We could have removed our own
// rule from the fakeRouter...but that would only work
// inside our own method!  If someone else is also
// doing the same thing, we would have an ugly little
// recursion where they call parse which calls us
// and then we clone router and call parse which calls them
// back, and forth and back and forth
// friends don't let friends use recursion!
   if (spl_object_hash($router) != spl_object_hash($trueRouter)) {
// oh no!  Abort, abort!
    return $vars;
   }

// we still want to clone the router passed to us, not the true router
// since the rules might be different
    $fakeRouter = clone $router;   
// note that at some point this will change from _rules to rules
    $fakeRouterRules = $fakeRouter->get('_rules');

   //now use the power of Joomla! to parse this uri!
   $vars = $fakeRouter->parse($vars);

    //what is the menu id?  what is the airspeed velocity of an unladen swallow?
    $menuId = ? isset($vars['itemId'])  $vars['itemId'] : 0;

// maybe you want to check menu parameters?  Please be smarter than this.
    if ($menuId == 67) {

    // change the option to be a different component.
    $vars['option'] == 'my_custom_component';
    }

   
    // either way, $vars is now the correct routing info
    // We will ALWAYS skip processing - no reason to process it twice!
    //if ($skipProcessing) {

elin

unread,
Apr 9, 2012, 2:52:29 PM4/9/12
to joomla-...@googlegroups.com
You can just put it in and hope that someone else comes in and cleans it up. That's the beauty of a wiki. But in the meantime do you mind if someone else does? And would it be ok to put it under jedl?

Elin

garyamort

unread,
Apr 9, 2012, 11:06:12 PM4/9/12
to joomla-...@googlegroups.com
hmm, like so?   http://docs.joomla.org/Router_Plugins 

Oh well...messy but there.  Assuming by jedl you mean the license...since it was all copied from there to begin with I keep the license I copied from to begin with so I guess it already is..  should have place a notice somewhere on to that affect to begin with.

Thandi Nhlapo

unread,
Apr 10, 2012, 5:07:44 AM4/10/12
to joomla-...@googlegroups.com

Hi All

Hope you had a wonderful week-end, i would like to update our contact page, where can i edit from.

garyamort

unread,
Apr 10, 2012, 9:40:51 AM4/10/12
to joomla-...@googlegroups.com
*grumble*...I learned something.....  I was trying to avoid that!

Made some updates:

Added links to some categories so it links forward/back.   Updated the title to bring it in line with existing titles.   Learned that in order to make code blocks, indentation and no blank lines is important.  Originally my code was broken into separate blocks, removing blank lines and making sure every line is indented fixed that.

Added a talk page in case anyone wishes to comment on whether global $app is preferred or if something else should be used.

The main thing I hate with Wiki's is that the page creation process has never been intuitive to me.   I'd also love if http://docs.joomla.org was moved into the Joomla-CMS repository in github.  docs.joomla.org can be mapped directly to the github wiki and then I wouldn't have to have yet another account with yet another password....and yet another user profile.  It would also then be simpler to link wiki articles directly to the code source in github[and vice versa.  Ie in the example plugins, links to the appropriate wiki pages would make things interactive.] 


elin

unread,
Apr 10, 2012, 4:35:29 PM4/10/12
to joomla-...@googlegroups.com
Thank you, thank you.

 I think there is a working group on docs right now so maybe we'll see something easier eventually.

Elin

Chris Davenport

unread,
Apr 10, 2012, 6:04:19 PM4/10/12
to joomla-...@googlegroups.com
Hi Gary,

See inline...

On 10 April 2012 14:40, garyamort <gary...@gmail.com> wrote:
*grumble*...I learned something.....  I was trying to avoid that!

Made some updates:

Added links to some categories so it links forward/back.   Updated the title to bring it in line with existing titles.   Learned that in order to make code blocks, indentation and no blank lines is important.  Originally my code was broken into separate blocks, removing blank lines and making sure every line is indented fixed that.

You can do it that way, but the easier way is to simply surround the code with <source lang="php"> and </source> tags.  The Geshi syntax highlighter will then render the code nice and cleanly and in colour without needing to alter any of the formatting.

Added a talk page in case anyone wishes to comment on whether global $app is preferred or if something else should be used.

The main thing I hate with Wiki's is that the page creation process has never been intuitive to me.   I'd also love if http://docs.joomla.org was moved into the Joomla-CMS repository in github.  docs.joomla.org can be mapped directly to the github wiki and then I wouldn't have to have yet another account with yet another password....and yet another user profile.  It would also then be simpler to link wiki articles directly to the code source in github[and vice versa.  Ie in the example plugins, links to the appropriate wiki pages would make things interactive.] 

Although the GitHub wiki is capable of handling a subset of MediaWiki syntax (although it doesn't by default), it is a long way from being able to handle our current documentation.

The plan is to eventually have @link statements in all the classes and methods in the Platform (and perhaps one day, the CMS too), which will link to appropriate wiki pages.  For example, see http://api.joomla.org/Joomla-Platform/Database/JTableNested.html where you can see that these links have already been entered.  It's a job I started a long time ago and haven't been able to get back to.  If anyone would like to take that on, please let me know.

Incidentally, it isn't necessary to transclude a copy of the JEDL license statement as that is the default license for the wiki anyway.

Chris.
 

--
You received this message because you are subscribed to the Google Groups "Joomla! CMS Development" group.
To view this discussion on the web, visit https://groups.google.com/d/msg/joomla-dev-cms/-/WxQlNnseU4AJ.

To post to this group, send an email to joomla-...@googlegroups.com.
To unsubscribe from this group, send email to joomla-dev-cm...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/joomla-dev-cms?hl=en-GB.



--
Chris Davenport
Joomla Leadership Team - Production Working Group
Joomla Documentation Coordinator

Mark Dexter

unread,
Apr 10, 2012, 7:31:50 PM4/10/12
to joomla-...@googlegroups.com
@Chris: I don't quite follow how the links work. In the JTableNested source, I see:

* @link        http://docs.joomla.org/JTableNested

which links to the wiki. But the link you gave links to api.joomla.org. That also has links to the Direct Descendant classes.

Where is it that you are wanting to put links? In the source code? If so, where would it link to? Where does the api.joomla.org fit into this?

Thanks. Mark

Chris Davenport

unread,
Apr 10, 2012, 7:42:12 PM4/10/12
to joomla-...@googlegroups.com
The @link statements go in the docblocks in the source code.  These are automatically parsed into HTML links by phpDocumentor when it generates api.joomla.org.   Or indeed by any other software that parses the docblocks.

Chris.

Mark Dexter

unread,
Apr 10, 2012, 7:58:34 PM4/10/12
to joomla-...@googlegroups.com
OK. So the project is simply to enter the class name in the doc block, as in:

@link  http://docs.joomla.org/<class name>

Is that it? Thanks. Mark

garyamort

unread,
Apr 10, 2012, 8:54:59 PM4/10/12
to joomla-...@googlegroups.com


On Tuesday, April 10, 2012 7:42:12 PM UTC-4, Chris Davenport wrote:
The @link statements go in the docblocks in the source code.  These are automatically parsed into HTML links by phpDocumentor when it generates api.joomla.org.   Or indeed by any other software that parses the docblocks.

Speaking of phpDocumentor, what documenting tool is being used and what version?   

garyamort

unread,
Apr 11, 2012, 7:09:38 AM4/11/12
to joomla-...@googlegroups.com
Thanks for correcting my formatting Chris!


On Tuesday, April 10, 2012 6:04:19 PM UTC-4, Chris Davenport wrote:
Although the GitHub wiki is capable of handling a subset of MediaWiki syntax (although it doesn't by default), it is a long way from being able to handle our current documentation.


Out of curiosity, what doesn't it handle today?  I'm running an export/import of the current wiki to see how it ends up formatted when imported.  One of the things I like about the Github wiki process is that it is all stored in a git repository with the same api access as the other repositories.  So phpDocumentor could take tagged information directly from the sourcecode and insert/update the wiki.

Jon Neubauer

unread,
Apr 11, 2012, 10:45:26 AM4/11/12
to joomla-...@googlegroups.com

The main thing I hate with Wiki's is that the page creation process has never been intuitive to me.   I'd also love if http://docs.joomla.org was moved into the Joomla-CMS repository in github.  docs.joomla.org can be mapped directly to the github wiki and then I wouldn't have to have yet another account with yet another password....and yet another user profile.  It would also then be simpler to link wiki articles directly to the code source in github[and vice versa.  Ie in the example plugins, links to the appropriate wiki pages would make things interactive.] 

@Gary - it's interesting that you mention that - because this is something we are actively working on.  There's a lot of folks that think that the docs site is not working, and is presenting more hurdles than answers for both the documentation team and definitely for Joomla! users - I'd be interested in talking with you about some of the ideas we're working on, and ideas that you might have!
Reply all
Reply to author
Forward
0 new messages