Source for file class.modrewriteurlstack.php

Documentation is available at class.modrewriteurlstack.php

  1. <?php
  2. /**
  3.  * Includes mod rewrite url stack class.
  4.  *
  5.  * @author      Murat Purc <murat@purc.de>
  6.  * @copyright   © Murat Purc 2008
  7.  * @date        09.10.2008
  8.  * @package     Contenido
  9.  * @subpackage  ModRewrite
  10.  */
  11.  
  12.  
  13. /**
  14.  * Mod rewrite url stack class. Provides features to collect urls and to get the
  15.  * pretty path and names of categories/articles at one go.
  16.  *
  17.  * Main goal of this class is to collect urls and to get the urlpath and urlname
  18.  * of the related categories/articles at one go. This will reduce the queries
  19.  * against the database.
  20.  * Therefore the full advantage will be taken by rewriting the urls at codeoutput
  21.  * in front_content.php, where you will be able to collect all urls at once...
  22.  *
  23.  * Usage:
  24.  * <code>
  25.  * // get the instance
  26.  * $oMRUrlStack = ModRewriteUrlStack::getInstance();
  27.  *
  28.  * // add several urls to fill the stack
  29.  * $oMRUrlStack->add('front_content.php?idcat=123');
  30.  * $oMRUrlStack->add('front_content.php?idart=321');
  31.  * $oMRUrlStack->add('front_content.php?idcatart=213');
  32.  * $oMRUrlStack->add('front_content.php?idcatlang=213');
  33.  * $oMRUrlStack->add('front_content.php?idartlang=312');
  34.  *
  35.  * // now the first call will get the pretty path and names from database at one go
  36.  * $aPrettyParts = $oMRUrlStack->getPrettyUrlParts('front_content.php?idcat=123');
  37.  * echo $aPrettyParts['urlpath']; // something like 'Main-category-name/Category-name/Another-category-name/'
  38.  * echo $aPrettyParts['urlname']; // something like 'Name-of-an-article'
  39.  * </code>
  40.  *
  41.  * @author      Murat Purc <murat@purc.de>
  42.  * @copyright   © Murat Purc 2008
  43.  * @date        09.10.2008
  44.  * @package     Contenido
  45.  * @subpackage  ModRewrite
  46.  */
  47.  
  48.     /**
  49.      * Self instance
  50.      *
  51.      * @var  ModRewriteUrlStack 
  52.      */
  53.     private static $_instance;
  54.  
  55.     /**
  56.      * Database object
  57.      *
  58.      * @var  DB_Contenido 
  59.      */
  60.     private $_oDb;
  61.  
  62.     /**
  63.      * Array for urls
  64.      *
  65.      * @var  array 
  66.      */
  67.     private $_aUrls = array();
  68.  
  69.     /**
  70.      * Url stack array
  71.      *
  72.      * @var  array 
  73.      */
  74.     private $_aStack = array();
  75.  
  76.     /**
  77.      * Contenido related parameter array
  78.      *
  79.      * @var  array 
  80.      */
  81.     private $_aConParams = array(
  82.         'idcat' => 1'idart' => 1'lang' => 1'idcatlang' => 1'idcatart' => 1'idartlang' => 1
  83.     );
  84.  
  85.     /**
  86.      * Database tables array
  87.      *
  88.      * @var  array 
  89.      */
  90.     private $_aTab;
  91.  
  92.     /**
  93.      * Language id
  94.      *
  95.      * @var  int 
  96.      */
  97.     private $_idLang;
  98.  
  99.  
  100.     /**
  101.      * Constructor, sets some properties.
  102.      */
  103.     private function __construct({
  104.         $this->_oDb    = new DB_Contenido();
  105.         $this->_aTab   = mpGlobals::getInstance()->get('cfg/tab');
  106.         $this->_idLang = mpGlobals::getInstance()->get('lang');
  107.     }
  108.  
  109.  
  110.     /**
  111.      * Returns a instance of ModRewriteUrlStack (singleton implementation)
  112.      *
  113.      * @return  ModRewriteUrlStack 
  114.      */
  115.     public static function getInstance({
  116.         if (self::$_instance == null{
  117.             self::$_instance new ModRewriteUrlStack();
  118.         }
  119.         return self::$_instance;
  120.     }
  121.  
  122.  
  123.     /**
  124.      * Adds an url to the stack
  125.      *
  126.      * @param  string  Url, like front_content.php?idcat=123...
  127.      */
  128.     public function add($url{
  129.         $url  ModRewrite::urlPreClean($url);
  130.         if (isset($this->_aUrls[$url])) {
  131.             return;
  132.         }
  133.  
  134.         $aUrl $this->_extractUrl($url);
  135.  
  136.         // cleanup parameter
  137.         foreach ($aUrl['params'as $p => $v{
  138.             if (!isset($this->_aConParams[$p])) {
  139.                 unset($aUrl['params'][$p]);
  140.             }
  141.         }
  142.  
  143.         // add language id, if not available
  144.         if ((int) mr_arrayValue($aUrl['params']'lang'== 0{
  145.             $aUrl['params']['lang'$this->_idLang;
  146.         }
  147.  
  148.         $sStackId $this->_makeStackId($aUrl['params']);
  149.         $this->_aUrls[$url]       $sStackId;
  150.         $this->_aStack[$sStackIdarray('params' => $aUrl['params']);
  151.     }
  152.  
  153.  
  154.     /**
  155.      * Returns the pretty urlparts (only category path an article name) of the
  156.      * desired url.
  157.      *
  158.      * @param   string  Url, like front_content.php?idcat=123...
  159.      * @return  array   Assoziative array like
  160.      *  <code>
  161.      *  $arr['urlpath']
  162.      *  $arr['urlname']
  163.      *  </code>
  164.      */
  165.     public function getPrettyUrlParts($url{
  166.         if (!isset($this->_aUrls[$url])) {
  167.             $this->add($url);
  168.         }
  169.  
  170.         $sStackId $this->_aUrls[$url];
  171.         if (!isset($this->_aStack[$sStackId]['urlpath'])) {
  172. #            Contenido_mpDebug::getInstance()->addDebug($url . "\n" . $sStackId, 'ModRewriteUrlStack->getPrettyUrlParts() $url $sStackId');
  173.             $this->_chunkSetPrettyUrlParts();
  174.         }
  175.         $aPretty array(
  176.             'urlpath' => $this->_aStack[$sStackId]['urlpath'],
  177.             'urlname' => $this->_aStack[$sStackId]['urlname']
  178.         );
  179. #        Contenido_mpDebug::getInstance()->addDebug($aPretty, 'ModRewriteUrlStack->getPrettyUrlParts() $aPretty');
  180.         return $aPretty;
  181.     }
  182.  
  183.  
  184.     /**
  185.      * Extracts passed url using parse_urla and adds also the 'params' array to it
  186.      *
  187.      * @param   string  Url, like front_content.php?idcat=123...
  188.      * @return  array  Components containing result of parse_url with additional
  189.      *                  'params' array
  190.      */
  191.     private function _extractUrl($url{
  192.         $aUrl @parse_url($url);
  193.         if (isset($aUrl['query'])) {
  194.             $aUrl['query'str_replace('&amp;''&'$aUrl['query']);
  195.             parse_str($aUrl['query']$aUrl['params']);
  196.         }
  197.         if (!isset($aUrl['params']&& !is_array($aUrl['params'])) {
  198.             $aUrl['params'array();
  199.         }
  200.         return $aUrl;
  201.     }
  202.  
  203.  
  204.     /**
  205.      * Extracts article or category related parameter from passed params array
  206.      * and generates an identifier.
  207.      *
  208.      * @param   array   $aParams  Parameter array
  209.      * @return  string  Composed stack id
  210.      */
  211.     private function _makeStackId(array $aParams{
  212.         # idcatart
  213.         if ((int) mr_arrayValue($aParams'idart'0{
  214.             $sStackId 'idart_' $aParams['idart''_lang_' $aParams['lang'];
  215.         elseif ((int) mr_arrayValue($aParams'idartlang'0{
  216.             $sStackId 'idartlang_' $aParams['idartlang'];
  217.         elseif ((int) mr_arrayValue($aParams'idcatart'0{
  218.             $sStackId 'idcatart_' $aParams['idcatart''_lang_' $aParams['lang'];
  219.         elseif ((int) mr_arrayValue($aParams'idcat'0{
  220.             $sStackId 'idcat_' $aParams['idcat''_lang_' $aParams['lang'];
  221.         elseif ((int) mr_arrayValue($aParams'idcatlang'0{
  222.             $sStackId 'idcatlang_' $aParams['idcatlang'];
  223.         else {
  224.             $sStackId 'lang_' $aParams['lang'];
  225.         }
  226.         return $sStackId;
  227.     }
  228.  
  229.  
  230.     /**
  231.      * Main function to get the urlparts of urls.
  232.      *
  233.      * Composes the query by looping thru stored but non processed urls, executes
  234.      * the query and adds the (urlpath and urlname) result to the stack.
  235.      */
  236.     private function _chunkSetPrettyUrlParts({
  237.         // collect stack parameter to get urlpath and urlname
  238.         $aStack array();
  239.         foreach ($this->_aStack as $stackId => $item{
  240.             if (!isset($item['urlpath'])) {
  241.                 // pretty url is to create
  242.                 $aStack[$stackId$item;
  243.             }
  244.         }
  245.  
  246.         // now, it's time to compose the where clause of the query
  247.         $sWhere '';
  248.         foreach ($aStack as $stackId => $item{
  249.             $aP $item['params'];
  250.             if ((int) mr_arrayValue($aP'idart'0{
  251.                 $sWhere .= '(al.idart = ' $aP['idart'' AND al.idlang = ' $aP['lang'') OR ';
  252.             elseif ((int) mr_arrayValue($aP'idartlang'0{
  253.                 $sWhere .= '(al.idartlang = ' $aP['idartlang'') OR ';
  254.             elseif ((int) mr_arrayValue($aP'idcat'0{
  255.                 $sWhere .= '(cl.idcat = ' $aP['idcat'' AND cl.idlang = ' $aP['lang'' AND cl.startidartlang = al.idartlang) OR ';
  256.             elseif ((int) mr_arrayValue($aP'idcatart'0{
  257.                 $sWhere .= '(ca.idcatart = ' $aP['idcatart'' AND ca.idart = al.idart AND al.idlang = ' $aP['lang'') OR ';
  258.             elseif ((int) mr_arrayValue($aP'idcatlang'0{
  259.                 $sWhere .= '(cl.idcatlang = ' $aP['idcatlang'' AND cl.startidartlang = al.idartlang) OR ';
  260.             }
  261.         }
  262.         if ($sWhere == ''{
  263.             return;
  264.         }
  265.         $sWhere substr($sWhere0-4);
  266.         $sWhere str_replace(' OR '" OR \n"$sWhere);
  267.  
  268.         // compose query and execute it
  269.         $sql = <<<SQL
  270. SELECT
  271.         al.idartlang, al.idart, al.idlang, al.urlname, cl.idcatlang, cl.idcat,
  272.         cl.urlpath, ca.idcatart
  273. FROM
  274.         {$this->_aTab['art_lang']} AS al, {$this->_aTab['cat_lang']} AS cl, {$this->_aTab['cat_art']} AS ca
  275. WHERE
  276.         al.idart = ca.idart AND
  277.         ca.idcat = cl.idcat AND
  278.         al.idlang = cl.idlang AND
  279.         ( $sWhere )
  280. SQL;
  281.         Contenido_mpDebug::getInstance()->addDebug($sql'ModRewriteUrlStack->_chunkSetPrettyUrlParts() $sql');
  282.  
  283.         $aNewStack array();
  284.  
  285.         $this->_oDb->query($sql);
  286.         while ($this->_oDb->next_record()) {
  287.             $aRS $this->_oDb->Record;
  288.  
  289.             // check current recordset against existing entries in stack
  290.             foreach ($aStack as $stackId => $item{
  291.                 $bFound false;
  292.                 $aP $item['params'];
  293.                 if (mr_arrayValue($aP'idart'== $aRS['idart'&& mr_arrayValue($aP'lang'== $aRS['idlang']{
  294.                     $bFound true;
  295.                 elseif (mr_arrayValue($aP'idartlang'== $aRS['idartlang']{
  296.                     $bFound true;
  297.                 elseif (mr_arrayValue($aP'idcatart'== $aRS['idcatart'&& mr_arrayValue($aP'lang'== $aRS['idlang']{
  298.                     $bFound true;
  299.                 elseif (mr_arrayValue($aP'idcat'== $aRS['idcat'&& mr_arrayValue($aP'lang'== $aRS['idlang']{
  300.                     $bFound true;
  301.                 elseif (mr_arrayValue($aP'idcatlang'== $aRS['idcatlang']{
  302.                     $bFound true;
  303.                 }
  304.  
  305.                 if ($bFound{
  306.                     // matching entry found, add urlpath and urlname
  307.                     $aNewStack[$stackId]['urlpath'$aRS['urlpath'];
  308.                     $aNewStack[$stackId]['urlname'$aRS['urlname'];
  309.                     // remove from base stack
  310.                     unset($aStack[$stackId]);
  311.                     break;
  312.                 }
  313.  
  314.             }
  315.  
  316.         }
  317.         Contenido_mpDebug::getInstance()->addDebug($aNewStack'ModRewriteUrlStack->_chunkSetPrettyUrlParts() $aNewStack');
  318.  
  319.         // merge stack data
  320.         $this->_aStack array_merge($this->_aStack$aNewStack);
  321.     }
  322.  
  323. }

Documentation generated on Tue, 25 Nov 2008 22:07:29 +0100 by phpDocumentor 1.4.1