Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • PHP
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cUriBuilderMR
  • ModRewrite
  • ModRewrite_ContentController
  • ModRewrite_ContentExpertController
  • ModRewrite_ContentTestController
  • ModRewrite_ControllerAbstract
  • ModRewriteBase
  • ModRewriteController
  • ModRewriteDebugger
  • ModRewriteTest
  • ModRewriteUrlStack
  • ModRewriteUrlUtil

Functions

  • mr_arrayValue
  • mr_buildGeneratedCode
  • mr_buildNewUrl
  • mr_conCopyArtLang
  • mr_conMoveArticles
  • mr_conSaveArticle
  • mr_conSyncArticle
  • mr_debugOutput
  • mr_getConfiguration
  • mr_getConfigurationFilePath
  • mr_getRequest
  • mr_header
  • mr_i18n
  • mr_loadConfiguration
  • mr_queryAndNextRecord
  • mr_removeMultipleChars
  • mr_requestCleanup
  • mr_runFrontendController
  • mr_setClientLanguageId
  • mr_setConfiguration
  • mr_strCopyCategory
  • mr_strMovedownCategory
  • mr_strMoveSubtree
  • mr_strMoveUpCategory
  • mr_strNewCategory
  • mr_strNewTree
  • mr_strRenameCategory
  • mr_strSyncCategory
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: 
  3: /**
  4:  * This file contains the uri builder mod rewrite class.
  5:  *
  6:  * @package Plugin
  7:  * @subpackage ModRewrite
  8:  * @author Murat Purc <murat@purc.de>
  9:  * @copyright four for business AG <www.4fb.de>
 10:  * @license http://www.contenido.org/license/LIZENZ.txt
 11:  * @link http://www.4fb.de
 12:  * @link http://www.contenido.org
 13:  */
 14: 
 15: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 16: 
 17: /**
 18:  * Class to build frontend urls for advandced mod rewrite plugin.
 19:  *
 20:  * Extends abstract Contenido_UriBuilder class and implements the
 21:  * singleton pattern.
 22:  *
 23:  * Usage:
 24:  * <pre>
 25:  * cInclude('classes', 'uri/class.uriBuilder.MR.php');
 26:  * $url = 'front_content.php?idart=123';
 27:  * $mrUriBuilder = cUriBuilderMR::getInstance();
 28:  * $mrUriBuilder->buildUrl(array($url));
 29:  * $newUrl = $mrUriBuilder->getUrl();
 30:  * </pre>
 31:  *
 32:  * @todo add handling of absolute paths
 33:  * @todo standardize handling of fragments
 34:  * @package Plugin
 35:  * @subpackage ModRewrite
 36:  */
 37: class cUriBuilderMR extends cUriBuilder {
 38: 
 39:     /**
 40:      * Self instance
 41:      *
 42:      * @var cUriBuilderMR
 43:      */
 44:     private static $_instance;
 45: 
 46:     /**
 47:      * Cached rootdir.
 48:      *
 49:      * The rootdir can differ from the configured one if an alternate
 50:      * frontendpath is configured as client setting. In order to determine the
 51:      * current rootdir only once this is cached as static class member.
 52:      *
 53:      * @var string
 54:      */
 55:     private static $_cachedRootDir;
 56: 
 57:     /**
 58:      * Ampersand used for composing several parameter value pairs
 59:      *
 60:      * @var string
 61:      */
 62:     private $_sAmp = '&amp;';
 63: 
 64:     /**
 65:      * Is XHTML output?
 66:      *
 67:      * @var bool
 68:      */
 69:     private $_bIsXHTML = false;
 70: 
 71:     /**
 72:      * Is mod rewrite enabled?
 73:      *
 74:      * @var bool
 75:      */
 76:     private $_bMREnabled = false;
 77: 
 78:     /**
 79:      * Mod Rewrite configuration
 80:      *
 81:      * @var array
 82:      */
 83:     private $_aMrCfg = NULL;
 84: 
 85:     /**
 86:      * Constructor to create an instance of this class.
 87:      *
 88:      * Tries to set some member variables.
 89:      */
 90:     private function __construct() {
 91:         $this->sHttpBasePath = '';
 92:         if (ModRewrite::isEnabled()) {
 93:             $this->_aMrCfg = ModRewrite::getConfig();
 94:             $this->_bMREnabled = true;
 95:             $this->_bIsXHTML = (getEffectiveSetting('generator', 'xhtml', 'false') == 'false') ? false : true;
 96:             $this->_sAmp = ($this->_bIsXHTML) ? '&amp;' : '&';
 97:         }
 98:     }
 99: 
100:     /**
101:      * Returns a instance of cUriBuilderMR.
102:      *
103:      * @return cUriBuilderMR
104:      */
105:     public static function getInstance() {
106:         if (self::$_instance == NULL) {
107:             self::$_instance = new self();
108:         }
109:         return self::$_instance;
110:     }
111: 
112:     /**
113:      * Builds a URL based on defined mod rewrite settings.
114:      *
115:      * @param array $params
116:      *                                Parameter array, provides only following parameters:
117:      *                                <code>
118:      *                                $params[0] = 'front_content.php?idart=123...'
119:      *                                </code>
120:      * @param bool  $bUseAbsolutePath [optional]
121:      *                                Flag to use absolute path (not used at the moment)
122:      *
123:      * @return string
124:      *         New build url
125:      * @throws cDbException
126:      * @throws cException
127:      * @throws cInvalidArgumentException
128:      */
129:     public function buildUrl(array $params, $bUseAbsolutePath = false) {
130:         ModRewriteDebugger::add($params, 'cUriBuilderMR::buildUrl() $params');
131:         $urlDebug = array();
132:         $urlDebug['in'] = $params;
133: 
134:         $url = self::_buildUrl($params);
135: 
136:         $urlPrefix = '';
137:         if ($bUseAbsolutePath) {
138:             $hmlPath = cRegistry::getFrontendUrl();
139:             $aComp = parse_url($hmlPath);
140:             $urlPrefix = $aComp['scheme'] . '://' . $aComp['host'];
141:             if (mr_arrayValue($aComp, 'port', '') !== '') {
142:                 $urlPrefix .= ':' . $aComp['port'];
143:             }
144:         }
145: 
146:         $this->sUrl = $urlPrefix . $url;
147: 
148:         $urlDebug['out'] = $this->sUrl;
149:         ModRewriteDebugger::add($urlDebug, 'cUriBuilderMR::buildUrl() in -> out');
150:     }
151: 
152:     /**
153:      * Builds the SEO-URL by analyzing passed arguments
154:      * (parameter value pairs).
155:      *
156:      * @param array $aParams
157:      *         Parameter array
158:      *
159:      * @return string
160:      *         New build pretty url
161:      * @throws cDbException
162:      * @throws cException
163:      * @throws cInvalidArgumentException
164:      */
165:     private function _buildUrl(array $aParams) {
166:         // language should changed, set lang parameter
167:         if (isset($aParams['changelang'])) {
168:             $aParams['lang'] = $aParams['changelang'];
169:         }
170: 
171:         // build the query
172:         $sQuery = http_build_query($aParams);
173: 
174:         // get pretty url parts
175:         $oMRUrlStack = ModRewriteUrlStack::getInstance();
176:         $aPretty = $oMRUrlStack->getPrettyUrlParts('front_content.php?' . $sQuery);
177: 
178:         // get all non CONTENIDO related query parameter
179:         $sQuery = $this->_createUrlQueryPart($aParams);
180: 
181:         // some presettings of variables
182:         $aParts = array();
183: 
184:         // add client id/name if desired
185:         $param = $this->_getClientParameter($aParams);
186:         if ($param) {
187:             $aParts[] = $param;
188:         }
189: 
190:         // add language id/name if desired
191:         $param = $this->_getLanguageParameter($aParams);
192:         if ($param) {
193:             $aParts[] = $param;
194:         }
195: 
196:         // get path part of the url
197:         $sPath = $this->_getPath($aPretty);
198:         if ($sPath !== '') {
199:             $aParts[] = $sPath;
200:         }
201:         $sPath = implode('/', $aParts) . '/';
202: 
203:         // get pagename part of the url
204:         $sArticle = $this->_getArticleName($aPretty, $aParams);
205: 
206:         if ($sArticle !== '') {
207:             $sFileExt = $this->_aMrCfg['file_extension'];
208:         } else {
209:             $sFileExt = '';
210:         }
211: 
212:         $sPathAndArticle = $sPath . $sArticle . $sFileExt;
213: 
214:         // use lowercase url
215:         if ($this->_aMrCfg['use_lowercase_uri'] == 1) {
216:             $sPathAndArticle = cString::toLowerCase($sPathAndArticle);
217:         }
218: 
219:         // $sUrl = $this->_aMrCfg['rootdir'] . $sPathAndArticle . $sQuery;
220:         $sUrl = $sPathAndArticle . $sQuery;
221: 
222:         // remove double or more join parameter
223:         $sUrl = mr_removeMultipleChars('/', $sUrl);
224:         if (cString::getPartOfString($sUrl, -2) == '?=') {
225:             $sUrl = substr_replace($sUrl, '', -2);
226:         }
227: 
228:         // now convert CONTENIDO url to an AMR url
229:         $sUrl = ModRewriteUrlUtil::getInstance()->toModRewriteUrl($sUrl);
230: 
231:         // prepend rootdir as defined in config
232:         // $sUrl = $this->_aMrCfg['rootdir'] . $sUrl;
233:         // this version allows for multiple domains of a client
234:         $sUrl = self::getMultiClientRootDir($this->_aMrCfg['rootdir']) . $sUrl;
235: 
236:         // remove double slashes
237:         $sUrl = mr_removeMultipleChars('/', $sUrl);
238: 
239:         return $sUrl;
240:     }
241: 
242:     /**
243:      * Returns the defined rootdir.
244:      *
245:      * Allows for root dir being alternativly defined as path of setting
246:      * client/%frontend_path%.
247:      *
248:      * @param string $configuredRootDir
249:      *         defined rootdir
250:      *
251:      * @return string
252:      * @throws cDbException
253:      * @throws cException
254:      * @throws cInvalidArgumentException
255:      */
256:     public static function getMultiClientRootDir($configuredRootDir) {
257: 
258:         // return cached rootdir if set
259:         if (isset(self::$_cachedRootDir)) {
260:             return self::$_cachedRootDir;
261:         }
262: 
263:         // get props of current client
264:         $props = cRegistry::getClient()->getProperties();
265:         // $props = cRegistry::getClient()->getPropertiesByType('client');
266: 
267:         // return rootdir as defined in AMR if client has no props
268:         if (!is_array($props)) {
269:             self::$_cachedRootDir = $configuredRootDir;
270:             return $configuredRootDir;
271:         }
272: 
273:         foreach ($props as $prop) {
274:             // skip props that are not of type 'client'
275:             if ($prop['type'] != 'client') {
276:                 continue;
277:             }
278: 
279:             // skip props whose name does not contain 'frontend_path'
280:             if (false === strstr($prop['name'], 'frontend_path')) {
281:                 continue;
282:             }
283: 
284:             // current host & path (HTTP_HOST & REQUEST_URI)
285:             $httpHost = $_SERVER['HTTP_HOST'];
286:             $httpPath = $_SERVER['REQUEST_URI'];
287: 
288:             // host & path of configured alternative URL
289:             $propHost = parse_url($prop['value'], PHP_URL_HOST);
290:             $propPath = parse_url($prop['value'], PHP_URL_PATH);
291: 
292:             // skip if http host does not equal configured host (allowing for
293:             // optional www)
294:             if ($propHost != $httpHost && ('www.' . $propHost) != $httpHost && $propHost != 'www.' . $httpHost) {
295:                 continue;
296:             }
297: 
298:             // skip if http path does not start with configured path
299:             if (0 !== cString::findFirstPos($httpPath, $propPath)) {
300:                 continue;
301:             }
302: 
303:             // return path as specified in client settings
304:             self::$_cachedRootDir = $propPath;
305:             return $propPath;
306:         }
307: 
308:         // return rootdir as defined in AMR
309:         self::$_cachedRootDir = $configuredRootDir;
310:         return $configuredRootDir;
311:     }
312: 
313:     /**
314:      * Loops through given parameter array and creates the query part of
315:      * the URL.
316:      *
317:      * All non CONTENIDO related parameters will be excluded from
318:      * composition.
319:      *
320:      * @param array $aArgs
321:      *         associative parameter array
322:      * @return string
323:      *         composed query part for the URL
324:      *         like '?foo=bar&amp;param=value'
325:      */
326:     private function _createUrlQueryPart(array $aArgs) {
327:         // set list of parameter which are to ignore while setting additional
328:         // parameter
329:         $aIgnoredParams = array(
330:             'idcat',
331:             'idart',
332:             'lang',
333:             'client',
334:             'idcatart',
335:             'idartlang'
336:         );
337:         if ($this->_aMrCfg['use_language'] == 1) {
338:             $aIgnoredParams[] = 'changelang';
339:         }
340:         if ($this->_aMrCfg['use_client'] == 1) {
341:             $aIgnoredParams[] = 'changeclient';
342:         }
343: 
344:         // collect additional non CONTENIDO related parameters
345:         $sQuery = '';
346:         foreach ($aArgs as $p => $v) {
347:             if (!in_array($p, $aIgnoredParams)) {
348:                 // $sQuery .= urlencode(urldecode($p)) . '=' .
349:                 // urlencode(urldecode($v)) . $this->_sAmp;
350:                 $p = urlencode(urldecode($p));
351:                 if (is_array($v)) {
352:                     // handle query parameter like foobar[0}=a&foobar[1]=b...
353:                     foreach ($v as $p2 => $v2) {
354:                         $p2 = urlencode(urldecode($p2));
355:                         $v2 = urlencode(urldecode($v2));
356:                         $sQuery .= $p . '[' . $p2 . ']=' . $v2 . $this->_sAmp;
357:                     }
358:                 } else {
359:                     $v = urlencode(urldecode($v));
360:                     $sQuery .= $p . '=' . $v . $this->_sAmp;
361:                 }
362:             }
363:         }
364:         if (cString::getStringLength($sQuery) > 0) {
365:             $sQuery = '?' . cString::getPartOfString($sQuery, 0, -cString::getStringLength($this->_sAmp));
366:         }
367:         return $sQuery;
368:     }
369: 
370:     /**
371:      * Returns client id or name depending on settings.
372:      *
373:      * @param array $aArgs
374:      *         Additional arguments
375:      * @return mixed
376:      *         Client id, client name or NULL
377:      */
378:     private function _getClientParameter(array $aArgs) {
379:         global $client;
380: 
381:         // set client if desired
382:         if ($this->_aMrCfg['use_client'] == 1) {
383:             $iChangeClient = (isset($aArgs['changeclient'])) ? (int) $aArgs['changeclient'] : 0;
384:             $idclient = ($iChangeClient > 0) ? $iChangeClient : $client;
385:             if ($this->_aMrCfg['use_client_name'] == 1) {
386:                 return urlencode(ModRewrite::getClientName($idclient));
387:             } else {
388:                 return $idclient;
389:             }
390:         }
391:         return NULL;
392:     }
393: 
394:     /**
395:      * Returns language id or name depending on settings.
396:      *
397:      * @param array $aArgs
398:      *         Additional arguments
399:      * @return mixed
400:      *         Language id, language name or NULL
401:      */
402:     private function _getLanguageParameter(array $aArgs) {
403:         global $lang;
404: 
405:         // set language if desired
406:         if ($this->_aMrCfg['use_language'] == 1) {
407:             $iChangeLang = (isset($aArgs['changelang'])) ? (int) $aArgs['changelang'] : 0;
408:             $idlang = ($iChangeLang > 0) ? $iChangeLang : $lang;
409:             if ($this->_aMrCfg['use_language_name'] == 1) {
410:                 return urlencode(ModRewrite::getLanguageName($idlang));
411:             } else {
412:                 return $idlang;
413:             }
414:         }
415:         return NULL;
416:     }
417: 
418:     /**
419:      * Returns composed path of url (normally the category structure).
420:      *
421:      * @param array $aPretty
422:      *         Pretty url array
423:      * @return string
424:      *         Path
425:      */
426:     private function _getPath(array $aPretty) {
427:         $sPath = (isset($aPretty['urlpath'])) ? $aPretty['urlpath'] : '';
428: 
429:         // check start directory settings
430:         if ($this->_aMrCfg['startfromroot'] == 0 && (cString::getStringLength($sPath) > 0)) {
431:             // splitt string in array
432:             $aCategories = explode('/', $sPath);
433: 
434:             // remove first category
435:             array_shift($aCategories);
436: 
437:             // implode array with categories to new string
438:             $sPath = implode('/', $aCategories);
439:         }
440: 
441:         return $sPath;
442:     }
443: 
444:     /**
445:      * Returns articlename depending on current setting.
446:      *
447:      * @param array $aPretty
448:      *         Pretty url array
449:      * @param array $aArgs
450:      *         Additional arguments
451:      * @return string
452:      *         Articlename
453:      */
454:     private function _getArticleName(array $aPretty, array $aArgs) {
455:         $sArticle = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
456: 
457:         $iIdCat = (isset($aArgs['idcat'])) ? (int) $aArgs['idcat'] : 0;
458:         $iIdCatLang = (isset($aArgs['idcatlang'])) ? (int) $aArgs['idcatlang'] : 0;
459:         $iIdCatArt = (isset($aArgs['idcatart'])) ? (int) $aArgs['idcatart'] : 0;
460:         $iIdArt = (isset($aArgs['idart'])) ? (int) $aArgs['idart'] : 0;
461:         $iIdArtLang = (isset($aArgs['idartlang'])) ? (int) $aArgs['idartlang'] : 0;
462: 
463:         // category id was passed but not article id
464:         if (($iIdCat > 0 || $iIdCatLang > 0) && $iIdCatArt == 0 && $iIdArt == 0 && $iIdArtLang == 0) {
465:             $sArticle = '';
466:             if ($this->_aMrCfg['add_startart_name_to_url']) {
467:                 if ($this->_aMrCfg['default_startart_name'] !== '') {
468:                     // use default start article name
469:                     $sArticle = $this->_aMrCfg['default_startart_name'];
470:                 } else {
471:                     $sArticle = (isset($aPretty['urlname'])) ? $aPretty['urlname'] : '';
472:                 }
473:             } else {
474:                 // url is to create without article name
475:                 $sArticle = '';
476:             }
477:         }
478: 
479:         return $sArticle;
480:     }
481: }
482: 
CMS CONTENIDO 4.10.0 API documentation generated by ApiGen 2.8.0