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-2012 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.         $conf jApp::config();
  42.         if (isset($conf->_modulesPathList[$this->module])) {
  43.             $p $conf->_modulesPathList[$this->module];
  44.         else if (isset($conf->_externalModulesPathList[$this->module])) {
  45.             $p $conf->_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.  
  110.         $conf jApp::config()->urlengine;
  111.         if ($conf['enableParser']{
  112.  
  113.             $sel new jSelectorUrlCfgSig($conf['significantFile']);
  114.             jIncluder::inc($sel);
  115.             $snp  $conf['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']// given by jIncluder line 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.         $conf jApp::config()->urlengine;
  139.  
  140.         if ($conf['enableParser']{
  141.  
  142.             $sel new jSelectorUrlCfgSig($conf['significantFile']);
  143.             jIncluder::inc($sel);
  144.             $basepath $conf['basePath'];
  145.             if (strpos($scriptNamePath$basepath=== 0{
  146.                 $snp substr($scriptNamePath,strlen($basepath));
  147.             }
  148.             else {
  149.                 $snp $scriptNamePath;
  150.             }
  151.             $pos strrpos($snp$conf['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']// given by jIncluder line 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.  
  178.         $urlact null;
  179.         $isDefault false;
  180.         $url new jUrl($scriptNamePath$params$pathinfo);
  181.  
  182.         foreach ($this->dataParseUrl as $k=>$infoparsing{
  183.             // the first element indicates if the entry point is a default entry point or not
  184.             if ($k==0{
  185.                 $isDefault $infoparsing;
  186.                 continue;
  187.             }
  188.  
  189.             if (count($infoparsing7{
  190.                 // an handler will parse the request URI
  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(0, 1..), // list of integer which indicates for each
  234.                                 // dynamic value: 0: urlencode, 1:urlencode except '/', 2:escape, 4: lang, 8: locale
  235.  
  236.                 5=>array('bla'=>'whatIWant' ), // list of static values
  237.                 6=>false or array('secondaries','actions')
  238.                 */
  239.                 list($module$action$reg$dynamicValues$escapes,
  240.                      $staticValues$secondariesActions$needHttps$infoparsing;
  241.  
  242.                 if (isset($params['module']&& $params['module'!== $module)
  243.                     continue;
  244.  
  245.                 if ($module != '')
  246.                     $params['module'$module;
  247.  
  248.                 // if the action parameter exists in the current url
  249.                 // and if it is one of secondaries actions, then we keep it
  250.                 // else we take the action indicated in the url mapping
  251.                 if ($secondariesActions && isset($params['action']) ) {
  252.                     if (strpos($params['action']':'=== false{
  253.                         $params['action''default:'.$params['action'];
  254.                     }
  255.                     if (!in_array($params['action']$secondariesActions&& $action !=''{
  256.                         $params['action'$action;
  257.                     }
  258.                 }
  259.                 else {
  260.                     if ($action !='')
  261.                         $params['action'$action;
  262.                 }
  263.  
  264.                 // let's merge static parameters
  265.                 if ($staticValues{
  266.                     foreach ($staticValues as $n=>$v{
  267.                         if (!empty($v&& $v[0== '$'// special statique value
  268.                             $typeStatic $v[1];
  269.                             $v substr($v,2);
  270.                             if ($typeStatic == 'l')
  271.                                 jApp::config()->locale jLocale::langToLocale($v);
  272.                             else if ($typeStatic == 'L')
  273.                                 jApp::config()->locale $v;
  274.                         }
  275.                         $params[$n$v;
  276.                     }
  277.                 }
  278.  
  279.                 // now let's read dynamic parameters
  280.                 if (count($matches)) {
  281.                     array_shift($matches);
  282.                     foreach ($dynamicValues as $k=>$name){
  283.                         if (isset($matches[$k])) {
  284.                             if ($escapes[$k2{
  285.                                 $params[$namejUrl::unescape($matches[$k]);
  286.                             }
  287.                             else {
  288.                                 $params[$name$matches[$k];
  289.                                 if ($escapes[$k4{
  290.                                     $v $matches[$k];
  291.                                     if (preg_match('/^\w{2,3}$/'$v$m))
  292.                                         jApp::config()->locale jLocale::langToLocale($v);
  293.                                     else {
  294.                                         jApp::config()->locale $v;
  295.                                         $params[$namesubstr($v0strpos('_'));
  296.                                     }
  297.                                 }
  298.                                 else if ($escapes[$k8{
  299.                                     $v $matches[$k];
  300.                                     if (preg_match('/^\w{2,3}$/'$v$m)) {
  301.                                         jApp::config()->locale $params[$namejLocale::langToLocale($v);
  302.                                     }
  303.                                     else
  304.                                         jApp::config()->locale $v;
  305.                                 }
  306.                             }
  307.                         }
  308.                     }
  309.                 }
  310.                 $urlact new jUrlAction($params);
  311.                 break;
  312.             }
  313.         }
  314.         if (!$urlact{
  315.             if ($isDefault && $pathinfo == ''{
  316.                 // if we didn't find the url in the mapping, and if this is the default
  317.                 // entry point, then we do anything
  318.                 $urlact new jUrlAction($params);
  319.             }
  320.             else {
  321.                 try {
  322.                     $urlact jUrl::get(jApp::config()->urlengine['notfoundAct']array()jUrl::JURLACTION);
  323.                 }
  324.                 catch (Exception $e{
  325.                     $urlact new jUrlAction(array('module'=>'jelix''action'=>'error:notfound'));
  326.                 }
  327.             }
  328.         }
  329.         else if ($needHttps && $isHttps{
  330.             // the url is declared for HTTPS, but the request does not come from HTTPS
  331.             // -> 404 not found
  332.             $urlact new jUrlAction(array('module'=>'jelix''action'=>'error:notfound'));
  333.         }
  334.         return $urlact;
  335.     }
  336.  
  337.     /**
  338.     * Create a jurl object with the given action data
  339.     * @param jUrlAction $url  information about the action
  340.     * @return jUrl the url correspondant to the action
  341.     * @author      Laurent Jouanneau
  342.     * @copyright   2005 CopixTeam, 2005-2006 Laurent Jouanneau
  343.     *    very few lines of code are copyrighted by CopixTeam, written by Laurent Jouanneau
  344.     *    and released under GNU Lesser General Public Licence,
  345.     *    in an experimental version of Copix Framework v2.3dev20050901,
  346.     *    http://www.copix.org.
  347.     */
  348.     public function create($urlact{
  349.  
  350.         if ($this->dataCreateUrl == null{
  351.             $sel new jSelectorUrlCfgSig(jApp::config()->urlengine['significantFile']);
  352.             jIncluder::inc($sel);
  353.             $this->dataCreateUrl = $GLOBALS['SIGNIFICANT_CREATEURL'];
  354.         }
  355.  
  356.         $url new jUrl(''$urlact->params'');
  357.  
  358.         $module $url->getParam('module'jContext::get());
  359.         $action $url->getParam('action');
  360.  
  361.         // let's try to retrieve informations corresponding
  362.         // to the given action. this informations will allow us to build
  363.         // the url
  364.         $id $module.'~'.$action.'@'.$urlact->requestType;
  365.         $urlinfo null;
  366.         if (isset ($this->dataCreateUrl [$id])) {
  367.             $urlinfo $this->dataCreateUrl[$id];
  368.             $url->delParam('module');
  369.             $url->delParam('action');
  370.         }
  371.         else {
  372.             $id $module.'~*@'.$urlact->requestType;
  373.             if (isset ($this->dataCreateUrl[$id])) {
  374.                 $urlinfo $this->dataCreateUrl[$id];
  375.                 if ($urlinfo[0!= || $urlinfo[3=== true)
  376.                     $url->delParam('module');
  377.             }
  378.             else {
  379.                 $id '@'.$urlact->requestType;
  380.                 if (isset ($this->dataCreateUrl [$id])) {
  381.                     $urlinfo $this->dataCreateUrl[$id];
  382.                 }
  383.                 else {
  384.                     throw new Exception("Significant url engine doesn't find corresponding url to this action :".$module.'~'.$action.'@'.$urlact->requestType);
  385.                 }
  386.             }
  387.         }
  388.         /*
  389.         urlinfo =
  390.           or array(0,'entrypoint', https true/false, 'handler selector', 'basepathinfo')
  391.           or array(1,'entrypoint', https true/false,
  392.                   array('year','month',), // list of dynamic values included in the url
  393.                   array(true, false..), // list of integers which indicates for each
  394.                                         // dynamic value: 0: urlencode, 1:urlencode except '/', 2:escape
  395.                   "/news/%1/%2/", // the url
  396.                   true/false, // false : this is a secondary action
  397.                   array('bla'=>'whatIWant' ) // list of static values
  398.                   )
  399.           or array(2,'entrypoint', https true/false), // for the patterns "@request"
  400.           or array(3,'entrypoint', https true/false), // for the patterns "module~@request"
  401.           or array(4, array(1,...), array(1,...)...)
  402.         */
  403.         if ($urlinfo[0== 4{
  404.             // an action is mapped to several urls
  405.             // so it isn't finished. Let's find building information
  406.             // into the array
  407.             $l count($urlinfo);
  408.             $urlinfofound null;
  409.             for ($i=1$i $l$i++{
  410.                 $ok true;
  411.                 // verify that given static parameters of the action correspond
  412.                 // to those defined for this url
  413.                 foreach ($urlinfo[$i][7as $n=>$v{
  414.                     // specialStatic are static values for which the url engine
  415.                     // can compare not only with a given url parameter value, but
  416.                     // also with a value stored some where (typically, a configuration value)
  417.                     $specialStatic (!empty($v&& $v[0== '$');
  418.                     $paramStatic $url->getParam($nnull);
  419.                     if ($specialStatic// special statique value
  420.                         $typePS $v[1];
  421.                         $v substr($v,2);
  422.                         if ($typePS == 'l'{
  423.                             if ($paramStatic === null)
  424.                                 $paramStatic jLocale::getCurrentLang();
  425.                             else if (preg_match('/^(\w{2,3})_\w{2,3}$/'$paramStatic$m)) // if the value is a locale instead of lang, translate it
  426.                                 $paramStatic $m[1];
  427.                             }
  428.                         }
  429.                         elseif ($typePS == 'L'{
  430.                             if ($paramStatic === null)
  431.                                 $paramStatic jApp::config()->locale;
  432.                             else if (preg_match('/^\w{2,3}$/'$paramStatic$m)) // if the value is a lang instead of locale, translate it
  433.                                 $paramStatic jLocale::langToLocale($paramStatic);
  434.                             }
  435.                         }
  436.                     }
  437.  
  438.                     if ($paramStatic != $v{
  439.                         $ok false;
  440.                         break;
  441.                     }
  442.                 }
  443.                 if ($ok{
  444.                     // static parameters correspond: we found our informations
  445.                     $urlinfofound $urlinfo[$i];
  446.                     break;
  447.                 }
  448.             }
  449.             if ($urlinfofound !== null{
  450.                 $urlinfo $urlinfofound;
  451.             }
  452.             else {
  453.                 $urlinfo $urlinfo[1];
  454.             }
  455.         }
  456.  
  457.         // at this step, we have informations to build the url
  458.  
  459.         $url->scriptName jApp::config()->urlengine['basePath'].$urlinfo[1];
  460.         if ($urlinfo[2])
  461.             $url->scriptName jApp::coord()->request->getServerURI(true).$url->scriptName;
  462.  
  463.         if ($urlinfo[1&& !jApp::config()->urlengine['multiview']{
  464.             $url->scriptName .= jApp::config()->urlengine['entrypointExtension'];
  465.         }
  466.  
  467.         // for some request types, parameters aren't in the url
  468.         // so we remove them
  469.         // it's a bit dirty to do that hardcoded here, but it would be a pain
  470.         // to load the request class to check whether we can remove or not
  471.         if (in_array($urlact->requestTypearray('xmlrpc','jsonrpc','soap'))) {
  472.             $url->clearParam();
  473.             return $url;
  474.         }
  475.  
  476.         if ($urlinfo[0== 0{
  477.             $s new jSelectorUrlHandler($urlinfo[3]);
  478.             $c $s->resource.'UrlsHandler';
  479.             $handler new $c();
  480.             $handler->create($urlact$url);
  481.             if ($urlinfo[4!= ''{
  482.                 $url->pathInfo $urlinfo[4].$url->pathInfo;
  483.             }
  484.         }
  485.         elseif($urlinfo[0== 1{
  486.             $pi $urlinfo[5];
  487.             foreach ($urlinfo[3as $k=>$param){
  488.                 $typeParam $urlinfo[4][$k];
  489.                 $value $url->getParam($param,'');
  490.                 if ($typeParam 2{
  491.                     $value jUrl::escape($valuetrue);
  492.                 }
  493.                 else if ($typeParam 1{
  494.                     $value str_replace('%2F''/'urlencode($value));
  495.                 }
  496.                 else if ($typeParam 4{
  497.                     if ($value == ''{
  498.                         $value jLocale::getCurrentLang();
  499.                     }
  500.                     else if (preg_match('/^(\w{2,3})_\w{2,3}$/'$value$m)) {
  501.                         $value $m[1];
  502.                     }
  503.                 }
  504.                 else if ($typeParam 8{
  505.                     if ($value == ''{
  506.                         $value jApp::config()->locale;
  507.                     }
  508.                     else if (preg_match('/^\w{2,3}$/'$value$m)) {
  509.                         $value jLocale::langToLocale($value);
  510.                     }
  511.                 }
  512.                 else {
  513.                     $value urlencode($value);
  514.                 }
  515.                 $pi str_replace(':'.$param$value$pi);
  516.                 $url->delParam($param);
  517.             }
  518.             $url->pathInfo $pi;
  519.             if ($urlinfo[6])
  520.                 $url->setParam('action',$action);
  521.             // removed parameters corresponding to static values
  522.             foreach ($urlinfo[7as $name=>$value{
  523.                 $url->delParam($name);
  524.             }
  525.         }
  526.         elseif ($urlinfo[0== 3{
  527.             if ($urlinfo[3]{
  528.                 $url->delParam('module');
  529.             }
  530.         }
  531.  
  532.         return $url;
  533.     }
  534. }

Documentation generated on Mon, 26 Oct 2015 21:58:16 +0100 by phpDocumentor 1.4.3