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 jApp::tempPath('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-2011 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 jApp::tempPath('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.                 $isHttps ($request->getProtocol(== 'https://');
  122.                 return $this->_parse($request->urlScript$request->urlPathInfo$params$isHttps);
  123.             }
  124.         }
  125.  
  126.         $urlact new jUrlAction($params);
  127.         return $urlact;
  128.     }
  129.  
  130.     /**
  131.     * Parse some url components
  132.     * @param string $scriptNamePath    /path/index.php
  133.     * @param string $pathinfo          the path info part of the url (part between script name and query)
  134.     * @param array  $params            url parameters (query part e.g. $_REQUEST)
  135.     * @return jUrlAction 
  136.     */
  137.     public function parse($scriptNamePath$pathinfo$params){
  138.         global $gJConfig;
  139.  
  140.         if ($gJConfig->urlengine['enableParser']{
  141.  
  142.             $sel new jSelectorUrlCfgSig($gJConfig->urlengine['significantFile']);
  143.             jIncluder::inc($sel);
  144.             $basepath $gJConfig->urlengine['basePath'];
  145.             if (strpos($scriptNamePath$basepath=== 0{
  146.                 $snp substr($scriptNamePath,strlen($basepath));
  147.             }
  148.             else {
  149.                 $snp $scriptNamePath;
  150.             }
  151.             $pos strrpos($snp$gJConfig->urlengine['entrypointExtension']);
  152.             if ($pos !== false{
  153.                 $snp substr($snp,0,$pos);
  154.             }
  155.             $snp rawurlencode($snp);
  156.             $file jApp::tempPath('compiled/urlsig/'.$sel->file.'.'.$snp.'.entrypoint.php');
  157.             if (file_exists($file)) {
  158.                 require($file);
  159.                 $this->dataCreateUrl = $GLOBALS['SIGNIFICANT_CREATEURL']// fourni via le jIncluder ligne 127
  160.                 $this->dataParseUrl = $GLOBALS['SIGNIFICANT_PARSEURL'][$snp];
  161.                 return $this->_parse($scriptNamePath$pathinfo$paramsfalse);
  162.             }
  163.         }
  164.         $urlact new jUrlAction($params);
  165.         return $urlact;
  166.     }
  167.  
  168.     /**
  169.     *
  170.     * @param string $scriptNamePath    /path/index.php
  171.     * @param string $pathinfo          the path info part of the url (part between script name and query)
  172.     * @param array  $params            url parameters (query part e.g. $_REQUEST)
  173.     * @param boolean $isHttps          says if the given url is asked with https or not
  174.     * @return jUrlAction 
  175.     */
  176.     protected function _parse($scriptNamePath$pathinfo$params$isHttps){
  177.         global $gJConfig;
  178.  
  179.         $urlact null;
  180.         $isDefault false;
  181.         $url new jUrl($scriptNamePath$params$pathinfo);
  182.  
  183.         foreach ($this->dataParseUrl as $k=>$infoparsing{
  184.             // the first element indicates if the entry point is a default entry point or not
  185.             if ($k==0{
  186.                 $isDefault $infoparsing;
  187.                 continue;
  188.             }
  189.  
  190.             if (count($infoparsing7{
  191.                 list($module$action$reg$selectorHandler$secondariesActions$needHttps$infoparsing;
  192.                 $url2 clone $url;
  193.                 if ($reg != ''{
  194.                     if (preg_match($reg$pathinfo$m))
  195.                         $url2->pathInfo = isset($m[1])?$m[1]:'/';
  196.                     else
  197.                         continue;
  198.                 }
  199.                 $s new jSelectorUrlHandler($selectorHandler);
  200.                 include_once($s->getPath());
  201.                 $c $s->className.'UrlsHandler';
  202.                 $handler new $c();
  203.  
  204.                 $url2->params['module'$module;
  205.  
  206.                 // if the action parameter exists in the current url
  207.                 // and if it is one of secondaries actions, then we keep it
  208.                 // else we take the action indicated in the url mapping
  209.                 if ($secondariesActions && isset($params['action'])) {
  210.                     if (strpos($params['action']':'=== false{
  211.                         $params['action''default:'.$params['action'];
  212.                     }
  213.                     if (in_array($params['action']$secondariesActions))
  214.                         // action peut avoir été écrasé par une itération précédente
  215.                         $url2->params['action'$params['action'];
  216.                     else
  217.                         $url2->params['action'$action;
  218.                 }
  219.                 else {
  220.                     $url2->params['action'$action;
  221.                 }
  222.                 // appel au handler
  223.                 if ($urlact $handler->parse($url2)) {
  224.                     break;
  225.                 }
  226.             }
  227.             elseif (preg_match ($infoparsing[2]$pathinfo$matches)) {
  228.  
  229.                 /* we have this array
  230.                 array( 0=>'module', 1=>'action', 2=>'regexp_pathinfo',
  231.                 3=>array('year','month'), // list of dynamic value included in the url,
  232.                                       // alphabetical ascendant order
  233.                 4=>array(true, false),    // list of integers which indicates for each
  234.                                       // dynamic value: 0: urlencode, 1:urlencode except '/', 2:escape
  235.                 5=>array('bla'=>'whatIWant' ), // list of static values
  236.                 6=>false or array('secondaries','actions')
  237.                 */
  238.                 list($module$action$reg$dynamicValues$escapes,
  239.                      $staticValues$secondariesActions$needHttps$infoparsing;
  240.                 if (isset($params['module']&& $params['module'!== $module)
  241.                     continue;
  242.  
  243.                 if ($module != '')
  244.                     $params['module'$module;
  245.  
  246.                 // if the action parameter exists in the current url
  247.                 // and if it is one of secondaries actions, then we keep it
  248.                 // else we take the action indicated in the url mapping
  249.                 if ($secondariesActions && isset($params['action']) ) {
  250.                     if (strpos($params['action']':'=== false{
  251.                         $params['action''default:'.$params['action'];
  252.                     }
  253.                     if (!in_array($params['action']$secondariesActions&& $action !=''{
  254.                         $params['action'$action;
  255.                     }
  256.                 }
  257.                 else {
  258.                     if ($action !='')
  259.                         $params['action'$action;
  260.                 }
  261.  
  262.                 // let's merge static parameters
  263.                 if ($staticValues{
  264.                     $params array_merge ($params$staticValues);
  265.                 }
  266.  
  267.                 // now let's read dynamic parameters
  268.                 if (count($matches)) {
  269.                     array_shift($matches);
  270.                     foreach ($dynamicValues as $k=>$name){
  271.                         if (isset($matches[$k])) {
  272.                             if ($escapes[$k]==2{
  273.                                 $params[$namejUrl::unescape($matches[$k]);
  274.                             }
  275.                             else {
  276.                                 $params[$name$matches[$k];
  277.                             }
  278.                         }
  279.                     }
  280.                 }
  281.                 $urlact new jUrlAction($params);
  282.                 break;
  283.             }
  284.         }
  285.         if (!$urlact{
  286.             if ($isDefault && $pathinfo == ''{
  287.                 // if we didn't find the url in the mapping, and if this is the default
  288.                 // entry point, then we do anything
  289.                 $urlact new jUrlAction($params);
  290.             }
  291.             else {
  292.                 try {
  293.                     $urlact jUrl::get($gJConfig->urlengine['notfoundAct']array()jUrl::JURLACTION);
  294.                 }
  295.                 catch (Exception $e{
  296.                     $urlact new jUrlAction(array('module'=>'jelix''action'=>'error:notfound'));
  297.                 }
  298.             }
  299.         }
  300.         else if ($needHttps && $isHttps{
  301.             // the url is declared for HTTPS, but the request does not come from HTTPS
  302.             // -> 404 not found
  303.             $urlact new jUrlAction(array('module'=>'jelix''action'=>'error:notfound'));
  304.         }
  305.         return $urlact;
  306.     }
  307.  
  308.     /**
  309.     * Create a jurl object with the given action data
  310.     * @param jUrlAction $url  information about the action
  311.     * @return jUrl the url correspondant to the action
  312.     * @author      Laurent Jouanneau
  313.     * @copyright   2005 CopixTeam, 2005-2006 Laurent Jouanneau
  314.     *    very few lines of code are copyrighted by CopixTeam, written by Laurent Jouanneau
  315.     *    and released under GNU Lesser General Public Licence,
  316.     *    in an experimental version of Copix Framework v2.3dev20050901,
  317.     *    http://www.copix.org.
  318.     */
  319.     public function create($urlact{
  320.  
  321.         if ($this->dataCreateUrl == null{
  322.             $sel new jSelectorUrlCfgSig($GLOBALS['gJConfig']->urlengine['significantFile']);
  323.             jIncluder::inc($sel);
  324.             $this->dataCreateUrl = $GLOBALS['SIGNIFICANT_CREATEURL'];
  325.         }
  326.  
  327.         $url new jUrl(''$urlact->params'');
  328.  
  329.         $module $url->getParam('module'jContext::get());
  330.         $action $url->getParam('action');
  331.  
  332.         // let's try to retrieve informations corresponding
  333.         // to the given action. this informations will allow us to build
  334.         // the url
  335.         $id $module.'~'.$action.'@'.$urlact->requestType;
  336.         $urlinfo null;
  337.         if (isset ($this->dataCreateUrl [$id])) {
  338.             $urlinfo $this->dataCreateUrl[$id];
  339.             $url->delParam('module');
  340.             $url->delParam('action');
  341.         }
  342.         else {
  343.             $id $module.'~*@'.$urlact->requestType;
  344.             if (isset ($this->dataCreateUrl[$id])) {
  345.                 $urlinfo $this->dataCreateUrl[$id];
  346.                 if ($urlinfo[0!= || $urlinfo[3=== true)
  347.                     $url->delParam('module');
  348.             }
  349.             else {
  350.                 $id '@'.$urlact->requestType;
  351.                 if (isset ($this->dataCreateUrl [$id])) {
  352.                     $urlinfo $this->dataCreateUrl[$id];
  353.                 }
  354.                 else {
  355.                     throw new Exception("Significant url engine doesn't find corresponding url to this action :".$module.'~'.$action.'@'.$urlact->requestType);
  356.                 }
  357.             }
  358.         }
  359.         /*
  360.         urlinfo =
  361.           or array(0,'entrypoint', https true/false, 'handler selector', 'basepathinfo')
  362.           or array(1,'entrypoint', https true/false,
  363.                   array('year','month',), // list of dynamic values included in the url
  364.                   array(true, false..), // list of integers which indicates for each
  365.                                         // dynamic value: 0: urlencode, 1:urlencode except '/', 2:escape
  366.                   "/news/%1/%2/", // the url
  367.                   true/false, // false : this is a secondary action
  368.                   array('bla'=>'whatIWant' ) // list of static values
  369.                   )
  370.           or array(2,'entrypoint', https true/false), // for the patterns "@request"
  371.           or array(3,'entrypoint', https true/false), // for the patterns "module~@request"
  372.           or array(4, array(1,...), array(1,...)...)
  373.         */
  374.         if ($urlinfo[0== 4{
  375.             // an action is mapped to several urls
  376.             // so it isn't finished. Let's find building information
  377.             // into the array
  378.             $l count($urlinfo);
  379.             $urlinfofound null;
  380.             for ($i=1$i $l$i++{
  381.                 $ok true;
  382.                 // verify that given static parameters of the action correspond
  383.                 // to those defined for this url
  384.                 foreach ($urlinfo[$i][7as $n=>$v{
  385.                     if ($url->getParam($n,''!= $v{
  386.                         $ok false;
  387.                         break;
  388.                     }
  389.                 }
  390.                 if ($ok{
  391.                     // static parameters correspond: we found our informations
  392.                     $urlinfofound $urlinfo[$i];
  393.                     break;
  394.                 }
  395.             }
  396.             if ($urlinfofound !== null{
  397.                 $urlinfo $urlinfofound;
  398.             }
  399.             else {
  400.                 $urlinfo $urlinfo[1];
  401.             }
  402.         }
  403.  
  404.         // at this step, we have informations to build the url
  405.  
  406.         $url->scriptName $GLOBALS['gJConfig']->urlengine['basePath'].$urlinfo[1];
  407.         if ($urlinfo[2])
  408.             $url->scriptName $GLOBALS['gJCoord']->request->getServerURI(true).$url->scriptName;
  409.  
  410.         if ($urlinfo[1&& !$GLOBALS['gJConfig']->urlengine['multiview']{
  411.             $url->scriptName .= $GLOBALS['gJConfig']->urlengine['entrypointExtension'];
  412.         }
  413.  
  414.         // pour certains types de requete, les paramètres ne sont pas dans l'url
  415.         // donc on les supprime
  416.         // c'est un peu crade de faire ça en dur ici, mais ce serait lourdingue
  417.         // de charger la classe request pour savoir si on peut supprimer ou pas
  418.         if (in_array($urlact->requestTypearray('xmlrpc','jsonrpc','soap'))) {
  419.             $url->clearParam();
  420.             return $url;
  421.         }
  422.  
  423.         if ($urlinfo[0== 0{
  424.             $s new jSelectorUrlHandler($urlinfo[3]);
  425.             $c $s->resource.'UrlsHandler';
  426.             $handler new $c();
  427.             $handler->create($urlact$url);
  428.             if ($urlinfo[4!= ''{
  429.                 $url->pathInfo $urlinfo[4].$url->pathInfo;
  430.             }
  431.         }
  432.         elseif($urlinfo[0== 1{
  433.             $pi $urlinfo[5];
  434.             foreach ($urlinfo[3as $k=>$param){
  435.                 switch ($urlinfo[4][$k]{
  436.                     case 2:
  437.                         $value jUrl::escape($url->getParam($param,''),true);
  438.                         break;
  439.                     case 1:
  440.                         $value str_replace('%2F''/',urlencode($url->getParam($param,'')));
  441.                         break;
  442.                     default:
  443.                         $value urlencode($url->getParam($param,''));
  444.                         break;
  445.                 }
  446.                 $pi str_replace(':'.$param$value$pi);
  447.                 $url->delParam($param);
  448.             }
  449.             $url->pathInfo $pi;
  450.             if ($urlinfo[6])
  451.                 $url->setParam('action',$action);
  452.             // removed parameters corresponding to static values
  453.             foreach ($urlinfo[7as $name=>$value{
  454.                 $url->delParam($name);
  455.             }
  456.         }
  457.         elseif ($urlinfo[0== 3{
  458.             if ($urlinfo[3]{
  459.                 $url->delParam('module');
  460.             }
  461.         }
  462.  
  463.         return $url;
  464.     }
  465. }

Documentation generated on Mon, 19 Sep 2011 14:14:13 +0200 by phpDocumentor 1.4.3