Source for file class.modrewritecontroller.php

Documentation is available at class.modrewritecontroller.php

  1. <?php
  2. /**
  3.  * Includes Mod Rewrite controller class.
  4.  *
  5.  * @author      Murat Purc <murat@purc.de>
  6.  * @copyright   © Murat Purc 2008
  7.  * @package     Contenido
  8.  * @subpackage  ModRewrite
  9.  */
  10.  
  11.  
  12. defined('CON_FRAMEWORK') or die('Illegal call');
  13.  
  14.  
  15. /**
  16.  * Mod Rewrite controller class. Extracts url parts and sets some necessary globals like:
  17.  * - $idart
  18.  * - $idcat
  19.  * - $client
  20.  * - $changeclient
  21.  * - $lang
  22.  * - $changelang
  23.  *
  24.  * @author      Murat Purc <murat@purc.de>
  25.  * @date        16.04.2008
  26.  * @package     Contenido
  27.  * @subpackage  ModRewrite
  28.  */
  29.  
  30.     /**
  31.      * Extracted request uri path parts by path separator '/'
  32.      *
  33.      * @var array 
  34.      */
  35.     private $_aParts;
  36.  
  37.     /**
  38.      * Extracted article name from request uri
  39.      *
  40.      * @var string 
  41.      */
  42.     private $_sArtName;
  43.  
  44.     /**
  45.      * Remaining path for path resolver (see $GLOBALS['path'])
  46.      *
  47.      * @var string 
  48.      */
  49.     private $_sPath;
  50.  
  51.     /**
  52.      * Incomming URL
  53.      *
  54.      * @var string 
  55.      */
  56.     private $_sIncommingUrl;
  57.  
  58.     /**
  59.      * Resolved URL
  60.      *
  61.      * @var string 
  62.      */
  63.     private $_sResolvedUrl;
  64.  
  65.     /**
  66.      * Client id used by this class
  67.      *
  68.      * @var int 
  69.      */
  70.     private $_iClientMR;
  71.  
  72.     /**
  73.      * Flag about occured errors
  74.      *
  75.      * @var bool 
  76.      */
  77.     private $_bError = false;
  78.  
  79.     /**
  80.      * Flag about found routing definition
  81.      *
  82.      * @var bool 
  83.      */
  84.     private $_bRoutingFound = false;
  85.  
  86.  
  87.     /**
  88.      * Constructor, sets several properties.
  89.      *
  90.      * @param  string  $incommingUrl  Incomming URL
  91.      */
  92.     public function __construct($incommingUrl) {
  93.         parent::initialize();
  94.         $this->_sIncommingUrl = $incommingUrl;
  95.         $this->_aParts        = array();
  96.     }
  97.  
  98.  
  99.     /**
  100.      * Getter for overwritten client id (see $GLOBALS['client'])
  101.      *
  102.      * @return  int  Client id
  103.      */
  104.     public function getClient() {
  105.         return parent::$_oGlobals->get('client');
  106.     }
  107.  
  108.  
  109.     /**
  110.      * Getter for overwritten change client id (see $GLOBALS['changeclient'])
  111.      *
  112.      * @return  int  Change client id
  113.      */
  114.     public function getChangeClient() {
  115.         return parent::$_oGlobals->get('changeclient');
  116.     }
  117.  
  118.  
  119.     /**
  120.      * Getter for article id (see $GLOBALS['idart'])
  121.      *
  122.      * @return  int  Article id
  123.      */
  124.     public function getIdArt() {
  125.         return parent::$_oGlobals->get('idart');
  126.     }
  127.  
  128.  
  129.     /**
  130.      * Getter for category id (see $GLOBALS['idcat'])
  131.      *
  132.      * @return  int  Category id
  133.      */
  134.     public function getIdCat() {
  135.         return parent::$_oGlobals->get('idcat');
  136.     }
  137.  
  138.  
  139.     /**
  140.      * Getter for language id (see $GLOBALS['lang'])
  141.      *
  142.      * @return  int  Language id
  143.      */
  144.     public function getLang() {
  145.         return parent::$_oGlobals->get('lang');
  146.     }
  147.  
  148.  
  149.     /**
  150.      * Getter for change language id (see $GLOBALS['change_lang'])
  151.      *
  152.      * @return  int  Change language id
  153.      */
  154.     public function getChangeLang() {
  155.         return parent::$_oGlobals->get('changelang');
  156.     }
  157.  
  158.  
  159.     /**
  160.      * Getter for path (see $GLOBALS['path'])
  161.      *
  162.      * @return  string  Path, used by path resolver
  163.      */
  164.     public function getPath() {
  165.         return $this->_sPath;
  166.     }
  167.  
  168.  
  169.     /**
  170.      * Getter for resolved url
  171.      *
  172.      * @return  string  Resolved url
  173.      */
  174.     public function getResolvedUrl() {
  175.         return $this->_sResolvedUrl;
  176.     }
  177.  
  178.  
  179.     /**
  180.      * Returns a flag about found routing definition
  181.      *
  182.      * return  bool  Flag about found routing
  183.      */
  184.     public function getRoutingFoundState() {
  185.         return $this->_bRoutingFound;
  186.     }
  187.  
  188.  
  189.     /**
  190.      * Getter for occured error state
  191.      *
  192.      * @return  bool  Flag for occured error
  193.      */
  194.     public function errorOccured(){
  195.         return $this->_bError;
  196.     }
  197.  
  198.  
  199.     /**
  200.      * Main function to call for mod rewrite related preprocessing jobs.
  201.      *
  202.      * Executes some private functions to extract request URI and to set needed membervariables
  203.      * (client, language, article id, category id, etc.)
  204.      */
  205.     public function execute() {
  206.         if (parent::isEnabled() == false) {
  207.             return;
  208.         }
  209.  
  210.         $this->_extractRequestUri();
  211.  
  212.         $this->_initializeClientId();
  213.  
  214.         $this->_setClientId();
  215.  
  216.         mr_loadConfiguration($this->_iClientMR);
  217.  
  218.         $this->_setLanguageId();
  219.  
  220.         // second call after setting client and language
  221.         $this->_extractRequestUri(true);
  222.  
  223.         $this->_setPathresolverSetting();
  224.  
  225.         $this->_setIdart();
  226.  
  227.         parent::$_oDebug->addDebug($this->_aParts, 'ModRewriteController::execute() _setIdart');
  228.  
  229.         $this->_postValidation();
  230.     }
  231.  
  232.  
  233.     /**
  234.      * Extracts request URI and sets member variables $this->_sArtName and $this->_aParts
  235.      *
  236.      * @param  bool $secondCall  Flag about second call of this function, is needed
  237.      *                            to re extract url if a routing definition was found
  238.      */
  239.     private function _extractRequestUri($secondCall=false) {
  240.         // check for defined rootdir
  241.         if (parent::getConfig('rootdir') !== '/' && strpos($_SERVER['REQUEST_URI'], $this->_sIncommingUrl) === 0) {
  242.             $this->_sIncommingUrl = str_replace(parent::getConfig('rootdir'), '/', $this->_sIncommingUrl);
  243.         }
  244.  
  245.         $aUrlComponents = $this->_parseUrl($this->_sIncommingUrl);
  246.         if (isset($aUrlComponents['path'])) {
  247. ##++##
  248.             if (parent::getConfig('rootdir') !== '/' && strpos($aUrlComponents['path'], parent::getConfig('rootdir')) === 0) {
  249.                 $aUrlComponents['path'] = str_replace(parent::getConfig('rootdir'), '/', $aUrlComponents['path']);
  250.             }
  251. ##++##
  252.  
  253.             if ($secondCall == true) {
  254.  
  255. #        parent::$_oDebug->addDebug($aUrlComponents, 'ModRewriteController::_extractRequestUri() 2. call $aUrlComponents');
  256.                 // @todo: implement real redirect of old front_content.php style urls
  257.  
  258.                 // check for routing definition
  259.                 $routings = parent::getConfig('routing');
  260.                 if (is_array($routings) && isset($routings[$aUrlComponents['path']])) {
  261.                     $aUrlComponents['path'] = $routings[$aUrlComponents['path']];
  262.                     if (strpos($aUrlComponents['path'], 'front_content.php') !== false) {
  263.                         // routing destination contains front_content.php
  264.  
  265.                         $this->_bRoutingFound = true;
  266.  
  267.                         // set client language, if not set before
  268.                         mr_setClientLanguageId(parent::$_oGlobals->get('client'));
  269.  
  270.                         //rebuild URL
  271.                         $url = mr_buildNewUrl($aUrlComponents['path']);
  272.  
  273.                         $aUrlComponents = $this->_parseUrl($url);
  274.  
  275.                         $this->_aParts = array();
  276.                     }
  277.                 } else {
  278.                     return;
  279.                 }
  280.             }
  281.  
  282.             $aPaths = explode('/', $aUrlComponents['path']);
  283.             foreach ($aPaths as $p => $item) {
  284.                 if (!empty($item)) {
  285.                     // pathinfo would also work
  286.                     $arr   = explode('.', $item);
  287.                     $count = count($arr);
  288.                     if ($count > 0 && '.' . strtolower($arr[$count-1]) == parent::getConfig('file_extension')) {
  289.                         array_pop($arr);
  290.                         $this->_sArtName = implode('.', $arr);
  291.                     } else {
  292.                         $this->_aParts[] = $item;
  293.                     }
  294.                 }
  295.             }
  296.  
  297.             if ($secondCall == true) {
  298.                 // reprocess extracting client and language
  299.                 $this->_setClientId();
  300.                 mr_loadConfiguration($this->_iClientMR);
  301.                 $this->_setLanguageId();
  302.             }
  303.  
  304.         }
  305.         parent::$_oDebug->addDebug($this->_aParts, 'ModRewriteController::_extractRequestUri() $this->_aParts');
  306.  
  307.         // loop parts array and remove existing 'front_content.php'
  308.         if ($this->_hasPartArrayItems()) {
  309.             foreach($this->_aParts as $p => $item) {
  310.                 if ($item == 'front_content.php') {
  311.                     unset($this->_aParts[$p]);
  312.                 }
  313.             }
  314.         }
  315.  
  316.         // set parts property top null, if needed
  317.         if ($this->_hasPartArrayItems() == false) {
  318.             $this->_aParts = null;
  319.         }
  320.  
  321.         // set artname to null if needed
  322.         if (!isset($this->_sArtName) || empty($this->_sArtName) || strlen($this->_sArtName) == 0) {
  323.             $this->_sArtName = null;
  324.         }
  325.  
  326.     }
  327.  
  328.  
  329.     /**
  330.      * Tries to initialize the client id
  331.      */
  332.     private function _initializeClientId() {
  333.         $client       = parent::$_oGlobals->get('client', 0);
  334.         $changeclient = parent::$_oGlobals->get('changeclient', 0);
  335.  
  336.         $this->_iClientMR = 0;
  337.         if ($client > 0 && $changeclient == 0) {
  338.             $this->_iClientMR = $client;
  339.         } elseif ($changeclient > 0) {
  340.             $this->_iClientMR = $changeclient;
  341.         } else {
  342.             $this->_iClientMR = parent::$_oGlobals->get('load_client');
  343.         }
  344.  
  345.         if ((int) $this->_iClientMR > 0) {
  346.             // set global client variable
  347.             parent::$_oGlobals->set('client', (int) $this->_iClientMR);
  348.         }
  349.     }
  350.  
  351.  
  352.     /**
  353.      * Sets client id
  354.      */
  355.     private function _setClientId() {
  356.         if ($this->_hasPartArrayItems() == false || parent::getConfig('use_client') !== 1) {
  357.             return;
  358.         }
  359.  
  360.         $client       = parent::$_oGlobals->get('client', 0);
  361.         $changeclient = parent::$_oGlobals->get('changeclient', 0);
  362.  
  363.         if (parent::getConfig('use_client_name') == 1) {
  364.             $changeclient     = ModRewrite::getClientId(array_shift($this->_aParts));
  365.             $this->_iClientMR = $changeclient;
  366.         } else {
  367.             $changeclient     = (int) array_shift($this->_aParts);
  368.             $this->_iClientMR = $changeclient;
  369.         }
  370.  
  371.         if (empty($changeclient) || (int) $changeclient == 0) {
  372.             $changeclient = parent::$_oGlobals->get('load_client');
  373.         }
  374.         if ($client > 0 && $changeclient !== $client) {
  375.             // overwrite existing client variable
  376.             $this->_iClientMR = $changeclient;
  377.             parent::$_oGlobals->set('client', $changeclient);
  378.         }
  379.  
  380.         parent::$_oGlobals->set('changeclient', $changeclient);
  381.     }
  382.  
  383.  
  384.     /**
  385.      * Sets language id
  386.      */
  387.     private function _setLanguageId() {
  388.         if ($this->_hasPartArrayItems() == false || parent::getConfig('use_language') !== 1) {
  389.             return;
  390.         }
  391.  
  392.         if (parent::getConfig('use_language_name') == 1) {
  393.             // thanks to Nicolas Dickinson for multi Client/Language BugFix
  394.             $changelang = ModRewrite::getLanguageId(array_shift($this->_aParts) , $this->_iClientMR);
  395.         } else {
  396.             $changelang = (int) array_shift($this->_aParts);
  397.         }
  398.  
  399.         if ((int) $changelang > 0) {
  400.             parent::$_oGlobals->set('lang', $changelang);
  401.             parent::$_oGlobals->set('changelang', $changelang);
  402.         }
  403.     }
  404.  
  405.  
  406.     /**
  407.      * Sets path resolver and category id
  408.      */
  409.     private function _setPathresolverSetting() {
  410.         if ($this->_hasPartArrayItems() == false) {
  411.             return;
  412.         }
  413.  
  414.         $this->_sPath = '/' . implode('/', $this->_aParts) . '/';
  415.  
  416.         $lang = parent::$_oGlobals->get('lang');
  417.  
  418.         if ($lang == null) {
  419.             if (parent::$_oGlobals->get('load_lang', 0) > 0) {
  420.                 // load_client is set in frontend/config.php
  421.  
  422.                 $lang = parent::$_oGlobals->get('load_lang');
  423.             } else {
  424.                 // get client id from table
  425.                 cInclude('classes', 'contenido/class.clientslang.php');
  426.                 $clCol = new cApiClientLanguageCollection();
  427.                 $clCol->setWhere('idclient', parent::$_oGlobals->get('client'));
  428.                 $clCol->query();
  429.                 if ($clItem = $clCol->next()) {
  430.                     $lang = $clItem->get('idlang');
  431.                 }
  432.             }
  433.             parent::$_oGlobals->set('lang', $lang);
  434.         }
  435.  
  436.         $idcat = (int) ModRewrite::getCatIdByUrlPath($this->_sPath);
  437.  
  438.         if ($idcat == 0) {
  439.             // category couldn't resolved
  440.             $this->_bError = true;
  441.             $idcat = null;
  442.         } else {
  443.             // unset $this->_sPath if $idcat could set, otherwhise it would be resolved again.
  444.             unset($this->_sPath);
  445.         }
  446.  
  447.         parent::$_oGlobals->set('idcat', $idcat);
  448.  
  449.         parent::$_oDebug->addDebug($idcat, 'ModRewriteController->_setPathresolverSetting $idcat');
  450.         parent::$_oDebug->addDebug($this->_sPath, 'ModRewriteController->_setPathresolverSetting $this->_sPath');
  451.     }
  452.  
  453.  
  454.     /**
  455.      * Sets article id
  456.      */
  457.     private function _setIdart() {
  458.         // startarticle name in url
  459.         if (parent::getConfig('add_startart_name_to_url') && isset($this->_sArtName)) {
  460.             if ($this->_sArtName == parent::getConfig('default_startart_name')) {
  461.                 // stored articlename is the default one, remove it ModRewrite::getArtIdByWebsafeName()
  462.                 // will find the real article name
  463.                 $this->_sArtName = null;
  464.             }
  465.         }
  466.  
  467.         $idcat = parent::$_oGlobals->get('idcat');
  468.         $idart = parent::$_oGlobals->get('idart');
  469.  
  470.         if ($idcat !== null && $this->_sArtName && $idart == null) {
  471.             // existing idcat with article name and no idart
  472.             $idart = ModRewrite::getArtIdByWebsafeName($this->_sArtName, $idcat);
  473.         } elseif ($idcat > 0 && $this->_sArtName == null && $idart == null) {
  474.  
  475.             if (parent::getConfig('add_startart_name_to_url') && parent::getConfig('default_startart_name') == '') {
  476.  
  477.                 // existing idcat without article name and idart
  478.                 cInclude('classes', 'class.article.php');
  479.                 $artColl = new ArticleCollection(array('idcat' => $idcat, 'start' => 1));
  480.                 if ($artItem = $artColl->startArticle()) {
  481.                     $idart = $artItem->get('idart');
  482.                 }
  483.  
  484.             }
  485.  
  486.         } elseif ($idcat == null && $idart == null && isset($this->_sArtName)) {
  487.             // no idcat and idart but article name
  488.             $idart = ModRewrite::getArtIdByWebsafeName($this->_sArtName);
  489.         }
  490.  
  491.         if ($idart !== null && (!$idart || (int) $idart == 0)) {
  492.             if (parent::getConfig('redirect_invalid_article_to_errorsite') == 1) {
  493.                 $this->_bError = true;
  494.                 $idart = null;
  495.             }
  496.         }
  497.  
  498.         parent::$_oGlobals->set('idart', $idart);
  499.  
  500.         parent::$_oDebug->addDebug($idart, 'ModRewriteController->_setIdart $idart');
  501.     }
  502.  
  503.  
  504.     /**
  505.      * Does post validation of the extracted data.
  506.      *
  507.      * One main goal of this function is to prevent duplicated content, which could happen, if
  508.      * the configuration 'startfromroot' is activated.
  509.      */
  510.     private function _postValidation() {
  511.         if ($this->_bError || $this->_bRoutingFound || !$this->_hasPartArrayItems()) {
  512.             return;
  513.         }
  514.  
  515.         if (parent::getConfig('startfromroot') == 1 && parent::getConfig('prevent_duplicated_content') == 1) {
  516.  
  517.             // prevention of duplicated content if '/firstcat/' is directly requested!
  518.  
  519.             $idcat = parent::$_oGlobals->get('idcat');
  520.             $idart = parent::$_oGlobals->get('idart');
  521.  
  522.             // compose new parameter
  523.             $param = '';
  524.             if ($idcat) {
  525.                 $param .= 'idcat=' . (int) $idcat;
  526.             }
  527.             if ($idart) {
  528.                 $param .= ($param !== '') ? '&idart=' . (int) $idart : 'idart=' . (int) $idart;
  529.             }
  530.  
  531.             if ($param == '') {
  532.                 return;
  533.             }
  534.  
  535.             // set client language, if not set before
  536.             mr_setClientLanguageId(parent::$_oGlobals->get('client'));
  537.  
  538.             //rebuild url
  539.             $url = mr_buildNewUrl('front_content.php?' . $param);
  540.  
  541.             $aUrlComponents = @parse_url($this->_sIncommingUrl);
  542.             $incommingUrl   = (isset($aUrlComponents['path'])) ? $aUrlComponents['path'] : '';
  543.  
  544.             parent::$_oDebug->addDebug($url, 'ModRewriteController->_postValidation validate url');
  545.             parent::$_oDebug->addDebug($incommingUrl, 'ModRewriteController->_postValidation incommingUrl');
  546.  
  547.             // now the new generated uri should be identical with the request uri
  548.             if ($incommingUrl !== $url) {
  549.                 $this->_bError = true;
  550.                 parent::$_oGlobals->set('idcat', null);
  551.             }
  552.         }
  553.     }
  554.  
  555.  
  556.     /**
  557.      * Parses the url using defined separators
  558.      *
  559.      * @param   string  $url  Incoming url
  560.      * @return  string  Parsed url
  561.      */
  562.     private function _parseUrl($url) {
  563.         $this->_sResolvedUrl = $url;
  564.  
  565.         $oMrUrlUtil = ModRewriteUrlUtil::getInstance();
  566.         $url = $oMrUrlUtil->toContenidoUrl($url);
  567.  
  568.         return @parse_url($url);
  569.     }
  570.  
  571.  
  572.     /**
  573.      * Returns state of parts property.
  574.      *
  575.      * @return  bool  True if $this->_aParts propery is an array and contains items
  576.      * @access  private
  577.      */
  578.     function _hasPartArrayItems() {
  579.         if (is_array($this->_aParts) && count($this->_aParts) > 0) {
  580.             return true;
  581.         } else {
  582.             return false;
  583.         }
  584.     }
  585.  
  586. }

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