Source for file Contenido_UrlBuilder_MR.class.php

Documentation is available at Contenido_UrlBuilder_MR.class.php

  1. <?php
  2. /**
  3.  * Project:
  4.  * Contenido Content Management System
  5.  *
  6.  * Description:
  7.  * Implementation of Contenido_UrlBuilder to build AMR (Advanced Mod Rewrite) Frontend-URLs
  8.  *
  9.  * Requirements:
  10.  * @con_php_req 5.0
  11.  *
  12.  * @package     Contenido
  13.  * @subpackage  ModRewrite
  14.  * @version     0.3
  15.  * @author      Murat Purc
  16.  * @copyright   © Murat Purc 2008
  17.  * @license     http://www.contenido.org/license/LIZENZ.txt
  18.  * @link        http://www.4fb.de
  19.  * @link        http://www.contenido.org
  20.  */
  21.  
  22.  
  23. defined('CON_FRAMEWORK') or die('Illegal call');
  24.  
  25.  
  26. cInclude('classes', 'UrlBuilder/Contenido_UrlBuilder.class.php');
  27. cInclude('classes', 'UrlBuilder/Contenido_UrlBuilderFactory.class.php');
  28.  
  29.  
  30. /**
  31.  * Class to build frontend urls for advandced mod rewrite plugin.
  32.  * Extends abstract Contenido_UrlBuilder class and implements singleton pattern.
  33.  *
  34.  * Usage:
  35.  * <code>
  36.  * cInclude('classes', 'UrlBuilder/Contenido_UrlBuilder_MR.class.php');
  37.  * $url = 'front_content.php?idart=123';
  38.  * $mrUrlBuilder = Contenido_UrlBuilder_MR::getInstance();
  39.  * $mrUrlBuilder->buildUrl(array($url));
  40.  * $newUrl = $mrUrlBuilder->getUrl();
  41.  * </code>
  42.  *
  43.  * @author      Murat Purc <murat@purc.de>
  44.  * @copyright   © Murat Purc 2008
  45.  * @package     Contenido
  46.  * @subpackage  ModRewrite
  47.  */
  48. class Contenido_UrlBuilder_MR extends Contenido_UrlBuilder {
  49.  
  50.     /**
  51.      * Self instance
  52.      *
  53.      * @var  Contenido_UrlBuilder_MR 
  54.      */
  55.     static private $_instance;
  56.  
  57.     /**
  58.      * Debugger instance
  59.      *
  60.      * @var  Contenido_mpDebug 
  61.      */
  62.     private $_oDebug;
  63.  
  64.     /**
  65.      * Ampersant used for composing several parameter value pairs
  66.      *
  67.      * @var  string 
  68.      */
  69.     private $_sAmp = '&amp;';
  70.  
  71.     /**
  72.      * Is XHTML output?
  73.      *
  74.      * @var  bool 
  75.      */
  76.     private $_bIsXHTML = false;
  77.  
  78.     /**
  79.      * Is mod rewrite enabled?
  80.      *
  81.      * @var  bool 
  82.      */
  83.     private $_bMREnabled = false;
  84.  
  85.     /**
  86.      * Mod Rewrite configuration
  87.      *
  88.      * @var  array 
  89.      */
  90.     private $_aMrCfg = null;
  91.  
  92.  
  93.     /**
  94.      * Constructor, tries to set some member variables.
  95.      */
  96.     private function __construct() {
  97.         $this->sHttpBasePath = '';
  98.         if (ModRewrite::isEnabled()) {
  99.             $this->_oDebug     = Contenido_mpDebug::getInstance();
  100.             $this->_aMrCfg     = ModRewrite::getConfig();
  101.             $this->_bMREnabled = true;
  102.             $this->_bIsXHTML   = (getEffectiveSetting('generator', 'xhtml', 'false') == 'false') ? false : true;
  103.             $this->_sAmp       = ($this->_bIsXHTML) ? '&' : '&amp;';
  104.         }
  105.     }
  106.  
  107.  
  108.     /**
  109.      * Returns a instance of Contenido_UrlBuilder_MR
  110.      *
  111.      * @return  Contenido_UrlBuilder_MR 
  112.      */
  113.     public static function getInstance() {
  114.         if (self::$_instance == null) {
  115.             self::$_instance = new Contenido_UrlBuilder_MR();
  116.         }
  117.         return self::$_instance;
  118.     }
  119.  
  120.  
  121.     /**
  122.      * Builds a URL based on defined mod rewrite settings.
  123.      *
  124.      * @param   array    $params  Parameter array, provides only following parameters:
  125.      *  <code>
  126.      *  $params[0] = 'front_content.php?idart=123...'
  127.      *  </code>
  128.      * @param   boolean  $bUseAbsolutePath  Flag to use absolute path (not used at the moment)
  129.      * @return  string   New build url
  130.      */
  131.     public function buildUrl(array $params, $bUseAbsolutePath=false) {
  132.         $url = (isset($params[0])) ? $params[0] : '';
  133.  
  134.         if ($this->_bMREnabled) {
  135.  
  136.             $url  = ModRewrite::urlPreClean($url);
  137.             $aUrl = ModRewrite::getClientFullUrlParts($url);
  138.             if (preg_match("/^front_content\.php(.*|.+?)/i", $aUrl['url'], $aHits) == 1) {
  139.                 $url = $aUrl['htmlpath'] . self::_buildUrl($aHits[1]);
  140.             } else {
  141.                 $this->_oDebug->addDebug($url, 'Contenido_UrlBuilder_MR::buildUrl() no match');
  142.             }
  143.         }
  144.  
  145. #        $urlDebug['out'] = $url;
  146. #        $this->_oDebug->addDebug($urlDebug, 'Contenido_UrlBuilder_MR::buildUrl() in -> out');
  147.  
  148.         $this->sUrl = $url;
  149.     }
  150.  
  151.  
  152.     /**
  153.      * Builds the SEO-URL by analyzing passed arguments (parameter value pairs)
  154.      *
  155.      * @param   string  $args  Arguments
  156.      * @return  string  New build pretty url
  157.      */
  158.     private function _buildUrl($args='') {
  159.         // check arguments, try to set anchor, if exists and do some cleanup
  160.         $sAnchor = '';
  161.         $aTmp = explode('#', $args);
  162.         if (count($aTmp) > 1) {
  163.             $args = $aTmp[0];
  164.             $sAnchor = '#' . urlencode(urldecode($aTmp[1]));
  165.         }
  166.         $args = str_replace('?', '', $args);
  167.  
  168.         // get pretty url parts
  169.         $oMRUrlStack = ModRewriteUrlStack::getInstance();
  170.         $aPretty = $oMRUrlStack->getPrettyUrlParts('front_content.php?' . $args);
  171.  
  172.         // extract arguments into arguments array
  173.         $aArgs = array();
  174.         parse_str($args, $aArgs);
  175.  
  176.         // get all non contenido related query parameter
  177.         $sQuery = $this->_createUrlQueryPart($aArgs);
  178.  
  179.         // some presettings of variables
  180.         $aParts = array();
  181.  
  182.         // add client id/name if desired
  183.         if ($param = $this->_getClientParameter($aParts, $aArgs)) {
  184.             $aParts[] = $param;
  185.         }
  186.  
  187.         // add language id/name if desired
  188.         if ($param = $this->_getLanguageParameter($aParts, $aArgs)) {
  189.             $aParts[] = $param;
  190.         }
  191.  
  192.         // get path part of the url
  193.         $sPath = $this->_getPath($aPretty);
  194.         if ($sPath !== '') {
  195.             $aParts[] = $sPath;
  196.         }
  197.         $sPath = implode('/', $aParts) . '/';
  198.  
  199.         // get pagename part of the url
  200.         $sArticle = $this->_getArticleName($aPretty, $aArgs);
  201.  
  202.         if ($sArticle !== '') {
  203.             $sFileExt = $this->_aMrCfg['file_extension'];
  204.         } else {
  205.             $sFileExt = '';
  206.         }
  207.  
  208.         $sPathAndArticle = $sPath . $sArticle . $sFileExt;
  209.         if ($this->_aMrCfg['use_lowercase_uri'] == 1) {
  210.             // use lowercase url
  211.             $sPathAndArticle = strtolower($sPathAndArticle);
  212.         }
  213.  
  214.         $sFullUrl = $this->_aMrCfg['rootdir'] . $sPathAndArticle . $sQuery . $sAnchor;
  215.  
  216.         // remove double or more join parameter
  217.         $sFullUrl = mr_removeMultipleChars('/', $sFullUrl);
  218.         if (substr($sFullUrl, -2) == '?=') {
  219.             $sFullUrl = substr_replace($sFullUrl, '', -2);
  220.         }
  221.  
  222.         // now convert Contenido url to an AMR url
  223.         $sFullUrl = ModRewriteUrlUtil::getInstance()->toModRewriteUrl($sFullUrl);
  224.  
  225.         return $sFullUrl;
  226.     }
  227.  
  228.  
  229.     /**
  230.      * Loops thru passed parameter array and creates the query part of the URL.
  231.      * All non Contenido related parameter will be excluded from composition.
  232.      *
  233.      * @param   array  $aArgs  Assoziative parameter array
  234.      * @return  string  Composed query part for the URL like '?foo=bar&amp;param=value'
  235.      */
  236.     private function _createUrlQueryPart(array $aArgs){
  237.         // set list of parameter which are to ignore while setting additional parameter
  238.         $aIgnoredParams = array(
  239.             'idcat', 'idart', 'lang', 'client', 'idcatart', 'idartlang'
  240.         );
  241.         if ($this->_aMrCfg['use_language'] == 1) {
  242.             $aIgnoredParams[] = 'changelang';
  243.         }
  244.         if ($this->_aMrCfg['use_client'] == 1) {
  245.             $aIgnoredParams[] = 'changeclient';
  246.         }
  247.  
  248.         // collect additional non contenido related parameters
  249.         $sQuery = '';
  250.         foreach ($aArgs as $p => $v) {
  251.             if (!in_array($p, $aIgnoredParams)) {
  252.                 $sQuery .= urlencode(urldecode($p)) . '=' . urlencode(urldecode($v)) . $this->_sAmp;
  253.             }
  254.         }
  255.         if (strlen($sQuery) > 0) {
  256.             $sQuery = '?' . substr($sQuery, 0, - strlen($this->_sAmp));
  257.         }
  258.         return $sQuery;
  259.     }
  260.  
  261.  
  262.     /**
  263.      * Returns client id or name depending on settings.
  264.      *
  265.      * @param   array   $aArgs     Additional arguments
  266.      * @return  mixed   Client id, client name or null
  267.      */
  268.     private function _getClientParameter(array $aArgs) {
  269.         // set client if desired
  270.         if ($this->_aMrCfg['use_client'] == 1) {
  271.             $iChangeClient = (isset($aArgs['changeclient'])) ? (int) $aArgs['changeclient'] : 0;
  272.             $idclient      = ($iChangeClient > 0) ? $iChangeClient : $GLOBALS['client'];
  273.             if ($this->_aMrCfg['use_client_name'] == 1) {
  274.                 return urlencode(ModRewrite::getClientName($idclient));
  275.             } else {
  276.                 return $idclient;
  277.             }
  278.         }
  279.         return null;
  280.     }
  281.  
  282.  
  283.     /**
  284.      * Returns language id or name depending on settings.
  285.      *
  286.      * @param   array   $aArgs     Additional arguments
  287.      * @return  mixed   Language id, language name or null
  288.      */
  289.     private function _getLanguageParameter(array $aArgs) {
  290.         // set language if desired
  291.         if ($this->_aMrCfg['use_language'] == 1) {
  292.             $iChangeLang = (isset($aArgs['changelang'])) ? (int) $aArgs['changelang'] : 0;
  293.             $idlang      = ($iChangeLang > 0) ? $iChangeLang : $GLOBALS['lang'];
  294.             if ($this->_aMrCfg['use_language_name'] == 1) {
  295.                 return urlencode(ModRewrite::getLanguageName($idlang));
  296.             } else {
  297.                 return $idlang;
  298.             }
  299.         }
  300.         return null;
  301.     }
  302.  
  303.  
  304.     /**
  305.      * Returns composed path of url (normally the category structure)
  306.      *
  307.      * @param   array   $aPretty   Pretty url array
  308.      * @return  string  Path
  309.      */
  310.     private function _getPath(array $aPretty) {
  311.         $sPath = (isset($aPretty['urlpath'])) ? $aPretty['urlpath'] : '';
  312.  
  313.         // check start directory settings
  314.         if ($this->_aMrCfg['startfromroot'] == 0 && (strlen($sPath) > 0)) {
  315.             // splitt string in array
  316.             $aCategories = explode('/', $sPath);
  317.  
  318.             // remove first category
  319.             array_shift($aCategories);
  320.  
  321.             // implode array with categories to new string
  322.             $sPath = implode('/', $aCategories);
  323.         }
  324.  
  325.         return $sPath;
  326.     }
  327.  
  328.  
  329.     /**
  330.      * Returns articlename depending on current setting
  331.      *
  332.      * @param   array   $aPretty   Pretty url array
  333.      * @param   array   $aArgs     Additional arguments
  334.      * @return  string  Articlename
  335.      */
  336.     private function _getArticleName(array $aPretty, array $aArgs) {
  337.  
  338.         $sArticle   = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
  339.  
  340.         $iIdCat     = (isset($aArgs['idcat'])) ? (int) $aArgs['idcat'] : 0;
  341.         $iIdCatLang = (isset($aArgs['idcatlang'])) ? (int) $aArgs['idcatlang'] : 0;
  342.         $iIdCatArt  = (isset($aArgs['idcatart'])) ? (int) $aArgs['idcatart'] : 0;
  343.         $iIdArt     = (isset($aArgs['idart'])) ? (int) $aArgs['idart'] : 0;
  344.         $iIdArtLang = (isset($aArgs['idartlang'])) ? (int) $aArgs['idartlang'] : 0;
  345.  
  346.         // category id was passed but not article id
  347.         if (($iIdCat > 0 || $iIdCatLang > 0) && $iIdCatArt == 0 && $iIdArt == 0 && $iIdArtLang == 0) {
  348.             $sArticle = '';
  349.             if ($this->_aMrCfg['add_startart_name_to_url']) {
  350.                 if ($this->_aMrCfg['default_startart_name'] !== '') {
  351.                     // use default start article name
  352.                     $sArticle = $this->_aMrCfg['default_startart_name'];
  353.                 } else {
  354.                     $sArticle = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
  355.                 }
  356.             } else {
  357.                 // url is to create without article name
  358.                 $sArticle = '';
  359.             }
  360.         }
  361.  
  362.         return $sArticle;
  363.     }
  364.  
  365.  
  366. }

Documentation generated on Sun, 21 Dec 2008 21:42:52 +0100 by phpDocumentor 1.4.1