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

Documentation generated on Sun, 08 Feb 2009 22:00:39 +0100 by phpDocumentor 1.4.1