Source for file significant.urls.php

Documentation is available at significant.urls.php

  1. <?php
  2. /**
  3.  * @package     jelix
  4.  * @subpackage  urls_engine
  5.  * @author      Laurent Jouanneau
  6.  * @copyright   2005-2011 Laurent Jouanneau
  7.  * @link        http://www.jelix.org
  8.  * @licence     GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html
  9.  */
  10.  
  11. /**
  12.  * a specific selector for the xml files which contains the configuration of the engine
  13.  * @package  jelix
  14.  * @subpackage urls_engine
  15.  * @author      Laurent Jouanneau
  16.  * @copyright   2005-2006 Laurent Jouanneau
  17.  */
  18. class jSelectorUrlCfgSig extends jSelectorCfg {
  19.     public $type = 'urlcfgsig';
  20.  
  21.     public function getCompiler(){
  22.         require_once(dirname(__FILE__).'/jSignificantUrlsCompiler.class.php');
  23.         $o = new jSignificantUrlsCompiler();
  24.         return $o;
  25.     }
  26.     public function getCompiledFilePath (){ return JELIX_APP_TEMP_PATH.'compiled/urlsig/'.$this->file.'.creationinfos.php';}
  27. }
  28.  
  29. /**
  30.  * a specific selector for user url handler
  31.  * @package  jelix
  32.  * @subpackage urls_engine
  33.  * @author      Laurent Jouanneau
  34.  * @copyright   2005-2006 Laurent Jouanneau
  35.  */
  36. class jSelectorUrlHandler extends jSelectorClass {
  37.     public $type = 'urlhandler';
  38.     protected $_suffix = '.urlhandler.php';
  39.  
  40.     protected function _createPath(){
  41.         global $gJConfig;
  42.         if (isset($gJConfig->_modulesPathList[$this->module])) {
  43.             $p = $gJConfig->_modulesPathList[$this->module];
  44.         } else if (isset($gJConfig->_externalModulesPathList[$this->module])) {
  45.             $p = $gJConfig->_externalModulesPathList[$this->module];
  46.         } else {
  47.             throw new jExceptionSelector('jelix~errors.selector.module.unknown', $this->toString());
  48.         }
  49.         $this->_path = $p.$this->_dirname.$this->subpath.$this->className.$this->_suffix;
  50.  
  51.         if (!file_exists($this->_path) || strpos($this->subpath,'..') !== false ) { // second test for security issues
  52.             throw new jExceptionSelector('jelix~errors.selector.invalid.target', array($this->toString(), $this->type));
  53.         }
  54.     }
  55.  
  56. }
  57. /**
  58.  * interface for user url handler
  59.  * @package  jelix
  60.  * @subpackage urls_engine
  61.  * @author      Laurent Jouanneau
  62.  * @copyright   2005-2006 Laurent Jouanneau
  63.  */
  64. interface jIUrlSignificantHandler {
  65.     /**
  66.     * create the jUrlAction corresponding to the given jUrl. Return false if it doesn't correspond
  67.     * @param jUrl $url 
  68.     * @return jUrlAction|false
  69.     */
  70.     public function parse($url);
  71.  
  72.     /**
  73.     * fill the given jurl object depending the jUrlAction object
  74.     * @param jUrlAction $urlact 
  75.     * @param jUrl $url 
  76.     */
  77.     public function create($urlact, $url);
  78. }
  79. /**
  80.  * an url engine to parse,analyse and create significant url
  81.  * it needs an urls.xml file in the config directory (see documentation)
  82.  * @package  jelix
  83.  * @subpackage urls_engine
  84.  * @author      Laurent Jouanneau
  85.  * @copyright   2005-2008 Laurent Jouanneau
  86.  */
  87. class significantUrlEngine implements jIUrlEngine {
  88.  
  89.     /**
  90.     * data to create significant url
  91.     * @var array 
  92.     */
  93.     protected $dataCreateUrl = null;
  94.  
  95.     /**
  96.     * data to parse and anaylise significant url, and to determine action, module etc..
  97.     * @var array 
  98.     */
  99.     protected $dataParseUrl =  null;
  100.  
  101.     /**
  102.      * Parse a url from the request
  103.      * @param jRequest $request 
  104.      * @param array  $params            url parameters
  105.      * @return jUrlAction 
  106.      * @since 1.1
  107.      */
  108.     public function parseFromRequest ($request, $params) {
  109.         global $gJConfig;
  110.  
  111.         if ($gJConfig->urlengine['enableParser']) {
  112.  
  113.             $sel = new jSelectorUrlCfgSig($gJConfig->urlengine['significantFile']);
  114.             jIncluder::inc($sel);
  115.             $snp  = $gJConfig->urlengine['urlScriptIdenc'];
  116.             $file = JELIX_APP_TEMP_PATH.'compiled/urlsig/'.$sel->file.'.'.$snp.'.entrypoint.php';
  117.             if (file_exists($file)) {
  118.                 require($file);
  119.                 $this->dataCreateUrl = & $GLOBALS['SIGNIFICANT_CREATEURL']; // fourni via le jIncluder ligne 99
  120.                 $this->dataParseUrl = & $GLOBALS['SIGNIFICANT_PARSEURL'][$snp];
  121.                 return $this->_parse($request->urlScript, $request->urlPathInfo, $params);
  122.             }
  123.         }
  124.  
  125.         $urlact = new jUrlAction($params);
  126.         return $urlact;
  127.     }
  128.  
  129.     /**
  130.     * Parse some url components
  131.     * @param string $scriptNamePath    /path/index.php
  132.     * @param string $pathinfo          the path info part of the url (part between script name and query)
  133.     * @param array  $params            url parameters (query part e.g. $_REQUEST)
  134.     * @return jUrlAction 
  135.     */
  136.     public function parse($scriptNamePath, $pathinfo, $params){
  137.         global $gJConfig;
  138.  
  139.         if ($gJConfig->urlengine['enableParser']) {
  140.  
  141.             $sel = new jSelectorUrlCfgSig($gJConfig->urlengine['significantFile']);
  142.             jIncluder::inc($sel);
  143.             $basepath = $gJConfig->urlengine['basePath'];
  144.             if (strpos($scriptNamePath, $basepath) === 0) {
  145.                 $snp = substr($scriptNamePath,strlen($basepath));
  146.             }
  147.             else {
  148.                 $snp = $scriptNamePath;
  149.             }
  150.             $pos = strrpos($snp, $gJConfig->urlengine['entrypointExtension']);
  151.             if ($pos !== false) {
  152.                 $snp = substr($snp,0,$pos);
  153.             }
  154.             $snp = rawurlencode($snp);
  155.             $file = JELIX_APP_TEMP_PATH.'compiled/urlsig/'.$sel->file.'.'.$snp.'.entrypoint.php';
  156.             if (file_exists($file)) {
  157.                 require($file);
  158.                 $this->dataCreateUrl = & $GLOBALS['SIGNIFICANT_CREATEURL']; // fourni via le jIncluder ligne 127
  159.                 $this->dataParseUrl = & $GLOBALS['SIGNIFICANT_PARSEURL'][$snp];
  160.                 return $this->_parse($scriptNamePath, $pathinfo, $params);
  161.             }
  162.         }
  163.         $urlact = new jUrlAction($params);
  164.         return $urlact;
  165.     }
  166.  
  167.     /**
  168.     *
  169.     * @param string $scriptNamePath    /path/index.php
  170.     * @param string $pathinfo          the path info part of the url (part between script name and query)
  171.     * @param array  $params            url parameters (query part e.g. $_REQUEST)
  172.     * @return jUrlAction 
  173.     */
  174.     protected function _parse($scriptNamePath, $pathinfo, $params){
  175.         global $gJConfig;
  176.  
  177.         $urlact = null;
  178.         $isDefault = false;
  179.         $url = new jUrl($scriptNamePath, $params, $pathinfo);
  180.  
  181.         foreach ($this->dataParseUrl as $k=>$infoparsing) {
  182.             // the first element indicates if the entry point is a default entry point or not
  183.             if ($k==0) {
  184.                 $isDefault = $infoparsing;
  185.                 continue;
  186.             }
  187.  
  188.             if (count($infoparsing) < 6) {
  189.                 list($module, $action, $reg, $selectorHandler, $secondariesActions) = $infoparsing;
  190.                 $url2 = clone $url;
  191.                 if ($reg != '') {
  192.                     if (preg_match($reg, $pathinfo, $m))
  193.                         $url2->pathInfo = isset($m[1])?$m[1]:'/';
  194.                     else
  195.                         continue;
  196.                 }
  197.                 $s = new jSelectorUrlHandler($selectorHandler);
  198.                 include_once($s->getPath());
  199.                 $c = $s->className.'UrlsHandler';
  200.                 $handler = new $c();
  201.  
  202.                 $url2->params['module'] = $module;
  203.  
  204.                 // if the action parameter exists in the current url
  205.                 // and if it is one of secondaries actions, then we keep it
  206.                 // else we take the action indicated in the url mapping
  207.                 if ($secondariesActions && isset($params['action'])) {
  208.                     if (strpos($params['action'], ':') === false) {
  209.                         $params['action'] = 'default:'.$params['action'];
  210.                     }
  211.                     if (in_array($params['action'], $secondariesActions))
  212.                         // action peut avoir été écrasé par une itération précédente
  213.                         $url2->params['action'] = $params['action'];
  214.                     else
  215.                         $url2->params['action'] = $action;
  216.                 }
  217.                 else {
  218.                     $url2->params['action'] = $action;
  219.                 }
  220.                 // appel au handler
  221.                 if ($urlact = $handler->parse($url2)) {
  222.                     break;
  223.                 }
  224.             }
  225.             elseif (preg_match ($infoparsing[2], $pathinfo, $matches)) {
  226.  
  227.                 /* we have this array
  228.                 array( 0=>'module', 1=>'action', 2=>'regexp_pathinfo',
  229.                 3=>array('year','month'), // list of dynamic value included in the url,
  230.                                       // alphabetical ascendant order
  231.                 4=>array(true, false),    // list of boolean which indicates for each
  232.                                       // dynamic value, if it is an escaped value or not
  233.                 5=>array('bla'=>'whatIWant' ), // list of static values
  234.                 6=>false or array('secondaries','actions')
  235.                 */
  236.                 list($module, $action, $reg, $dynamicValues, $escapes, $staticValues, $secondariesActions) = $infoparsing;
  237.                 if (isset($params['module']) && $params['module'] !== $module)
  238.                     continue;
  239.  
  240.                 if ($module != '')
  241.                     $params['module'] = $module;
  242.  
  243.                 // if the action parameter exists in the current url
  244.                 // and if it is one of secondaries actions, then we keep it
  245.                 // else we take the action indicated in the url mapping
  246.                 if ($secondariesActions && isset($params['action']) ) {
  247.                     if (strpos($params['action'], ':') === false) {
  248.                         $params['action'] = 'default:'.$params['action'];
  249.                     }
  250.                     if (!in_array($params['action'], $secondariesActions) && $action !='') {
  251.                         $params['action'] = $action;
  252.                     }
  253.                 }
  254.                 else {
  255.                     if ($action !='')
  256.                         $params['action'] = $action;
  257.                 }
  258.  
  259.                 // let's merge static parameters
  260.                 if ($staticValues) {
  261.                     $params = array_merge ($params, $staticValues);
  262.                 }
  263.  
  264.                 // now let's read dynamic parameters
  265.                 if (count($matches)) {
  266.                     array_shift($matches);
  267.                     foreach ($dynamicValues as $k=>$name){
  268.                         if (isset($matches[$k])) {
  269.                             if ($escapes[$k]) {
  270.                                 $params[$name] = jUrl::unescape($matches[$k]);
  271.                             }
  272.                             else {
  273.                                 $params[$name] = $matches[$k];
  274.                             }
  275.                         }
  276.                     }
  277.                 }
  278.                 $urlact = new jUrlAction($params);
  279.                 break;
  280.             }
  281.         }
  282.         if (!$urlact) {
  283.             if ($isDefault && $pathinfo == '') {
  284.                 // if we didn't find the url in the mapping, and if this is the default
  285.                 // entry point, then we do anything
  286.                 $urlact = new jUrlAction($params);
  287.             }
  288.             else {
  289.                 try {
  290.                     $urlact = jUrl::get($gJConfig->urlengine['notfoundAct'], array(), jUrl::JURLACTION);
  291.                 }
  292.                 catch (Exception $e) {
  293.                     $urlact = new jUrlAction(array('module'=>'jelix', 'action'=>'error:notfound'));
  294.                 }
  295.             }
  296.         }
  297.         return $urlact;
  298.     }
  299.  
  300.     /**
  301.     * Create a jurl object with the given action data
  302.     * @param jUrlAction $url  information about the action
  303.     * @return jUrl the url correspondant to the action
  304.     * @author      Laurent Jouanneau
  305.     * @copyright   2005 CopixTeam, 2005-2006 Laurent Jouanneau
  306.     *    very few lines of code are copyrighted by CopixTeam, written by Laurent Jouanneau
  307.     *    and released under GNU Lesser General Public Licence,
  308.     *    in an experimental version of Copix Framework v2.3dev20050901,
  309.     *    http://www.copix.org.
  310.     */
  311.     public function create($urlact) {
  312.  
  313.         if ($this->dataCreateUrl == null) {
  314.             $sel = new jSelectorUrlCfgSig($GLOBALS['gJConfig']->urlengine['significantFile']);
  315.             jIncluder::inc($sel);
  316.             $this->dataCreateUrl = & $GLOBALS['SIGNIFICANT_CREATEURL'];
  317.         }
  318.  
  319.         $url = new jUrl('', $urlact->params, '');
  320.  
  321.         $module = $url->getParam('module', jContext::get());
  322.         $action = $url->getParam('action');
  323.  
  324.         // let's try to retrieve informations corresponding
  325.         // to the given action. this informations will allow us to build
  326.         // the url
  327.         $id = $module.'~'.$action.'@'.$urlact->requestType;
  328.         $urlinfo = null;
  329.         if (isset ($this->dataCreateUrl [$id])) {
  330.             $urlinfo = $this->dataCreateUrl[$id];
  331.             $url->delParam('module');
  332.             $url->delParam('action');
  333.         }
  334.         else {
  335.             $id = $module.'~*@'.$urlact->requestType;
  336.             if (isset ($this->dataCreateUrl[$id])) {
  337.                 $urlinfo = $this->dataCreateUrl[$id];
  338.                 if ($urlinfo[0] != 3 || $urlinfo[3] === true)
  339.                     $url->delParam('module');
  340.             }
  341.             else {
  342.                 $id = '@'.$urlact->requestType;
  343.                 if (isset ($this->dataCreateUrl [$id])) {
  344.                     $urlinfo = $this->dataCreateUrl[$id];
  345.                 }
  346.                 else {
  347.                     throw new Exception("Significant url engine doesn't find corresponding url to this action :".$module.'~'.$action.'@'.$urlact->requestType);
  348.                 }
  349.             }
  350.         }
  351.         /*
  352.         urlinfo =
  353.           or array(0,'entrypoint', https true/false, 'handler selector', 'basepathinfo')
  354.           or array(1,'entrypoint', https true/false,
  355.                   array('year','month',), // list of dynamic values included in the url
  356.                   array(true, false..), // list of boolean which indicates for each
  357.                                         // dynamic value, if it is an escaped value or not
  358.                   "/news/%1/%2/", // the url
  359.                   true/false, // false : this is a secondary action
  360.                   array('bla'=>'whatIWant' ) // list of static values
  361.                   )
  362.           or array(2,'entrypoint', https true/false), // for the patterns "@request"
  363.           or array(3,'entrypoint', https true/false), // for the patterns "module~@request"
  364.           or array(4, array(1,...), array(1,...)...)
  365.         */
  366.         if ($urlinfo[0] == 4) {
  367.             // an action is mapped to several urls
  368.             // so it isn't finished. Let's find building information
  369.             // into the array
  370.             $l = count($urlinfo);
  371.             $urlinfofound = null;
  372.             for ($i=1; $i < $l; $i++) {
  373.                 $ok = true;
  374.                 // verify that given static parameters of the action correspond
  375.                 // to those defined for this url
  376.                 foreach ($urlinfo[$i][7] as $n=>$v) {
  377.                     if ($url->getParam($n,'') != $v) {
  378.                         $ok = false;
  379.                         break;
  380.                     }
  381.                 }
  382.                 if ($ok) {
  383.                     // static parameters correspond: we found our informations
  384.                     $urlinfofound = $urlinfo[$i];
  385.                     break;
  386.                 }
  387.             }
  388.             if ($urlinfofound !== null) {
  389.                 $urlinfo = $urlinfofound;
  390.             }
  391.             else {
  392.                 $urlinfo = $urlinfo[1];
  393.             }
  394.         }
  395.  
  396.         // at this step, we have informations to build the url
  397.  
  398.         $url->scriptName = $GLOBALS['gJConfig']->urlengine['basePath'].$urlinfo[1];
  399.         if ($urlinfo[2])
  400.             $url->scriptName = $GLOBALS['gJCoord']->request->getServerURI(true).$url->scriptName;
  401.  
  402.         if ($urlinfo[1] && !$GLOBALS['gJConfig']->urlengine['multiview']) {
  403.             $url->scriptName .= $GLOBALS['gJConfig']->urlengine['entrypointExtension'];
  404.         }
  405.  
  406.         // pour certains types de requete, les paramètres ne sont pas dans l'url
  407.         // donc on les supprime
  408.         // c'est un peu crade de faire ça en dur ici, mais ce serait lourdingue
  409.         // de charger la classe request pour savoir si on peut supprimer ou pas
  410.         if (in_array($urlact->requestType, array('xmlrpc','jsonrpc','soap'))) {
  411.             $url->clearParam();
  412.             return $url;
  413.         }
  414.  
  415.         if ($urlinfo[0] == 0) {
  416.             $s = new jSelectorUrlHandler($urlinfo[3]);
  417.             $c = $s->resource.'UrlsHandler';
  418.             $handler = new $c();
  419.             $handler->create($urlact, $url);
  420.             if ($urlinfo[4] != '') {
  421.                 $url->pathInfo = $urlinfo[4].$url->pathInfo;
  422.             }
  423.         }
  424.         elseif($urlinfo[0] == 1) {
  425.             $pi = $urlinfo[5];
  426.             foreach ($urlinfo[3] as $k=>$param){
  427.                 if ($urlinfo[4][$k]) {
  428.                     $pi = str_replace(':'.$param, jUrl::escape($url->getParam($param,''),true), $pi);
  429.                 }
  430.                 else {
  431.                     $pi = str_replace(':'.$param, urlencode($url->getParam($param,'')), $pi);
  432.                 }
  433.                 $url->delParam($param);
  434.             }
  435.             $url->pathInfo = $pi;
  436.             if ($urlinfo[6])
  437.                 $url->setParam('action',$action);
  438.             // removed parameters corresponding to static values
  439.             foreach ($urlinfo[7] as $name=>$value) {
  440.                 $url->delParam($name);
  441.             }
  442.         }
  443.         elseif ($urlinfo[0] == 3) {
  444.             if ($urlinfo[3]) {
  445.                 $url->delParam('module');
  446.             }
  447.         }
  448.  
  449.         return $url;
  450.     }
  451. }

Documentation generated on Thu, 19 Sep 2013 00:09:21 +0200 by phpDocumentor 1.4.3