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
    • SIWECOS
    • 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:  * AMR url stack class
  4:  *
  5:  * @package     Plugin
  6:  * @subpackage  ModRewrite
  7:  * @id          $Id$:
  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:  * Mod rewrite url stack class. Provides features to collect urls and to get the
 19:  * pretty path and names of categories/articles at one go.
 20:  *
 21:  * Main goal of this class is to collect urls and to get the urlpath and urlname
 22:  * of the related categories/articles at one go. This will reduce the queries
 23:  * against the database.
 24:  * Therefore the full advantage will be taken by rewriting the urls at codeoutput
 25:  * in front_content.php, where you will be able to collect all urls at once...
 26:  *
 27:  * Usage:
 28:  * <code>
 29:  * // get the instance
 30:  * $oMRUrlStack = ModRewriteUrlStack::getInstance();
 31:  *
 32:  * // add several urls to fill the stack
 33:  * $oMRUrlStack->add('front_content.php?idcat=123');
 34:  * $oMRUrlStack->add('front_content.php?idart=321');
 35:  * $oMRUrlStack->add('front_content.php?idcatart=213');
 36:  * $oMRUrlStack->add('front_content.php?idcatlang=213');
 37:  * $oMRUrlStack->add('front_content.php?idartlang=312');
 38:  *
 39:  * // now the first call will get the pretty path and names from database at one go
 40:  * $aPrettyParts = $oMRUrlStack->getPrettyUrlParts('front_content.php?idcat=123');
 41:  * echo $aPrettyParts['urlpath']; // something like 'Main-category-name/Category-name/Another-category-name/'
 42:  * echo $aPrettyParts['urlname']; // something like 'Name-of-an-article'
 43:  * </code>
 44:  *
 45:  * @author      Murat Purc <murat@purc.de>
 46:  * @package     Plugin
 47:  * @subpackage  ModRewrite
 48:  */
 49: class ModRewriteUrlStack {
 50: 
 51:     /**
 52:      * Self instance
 53:      *
 54:      * @var  ModRewriteUrlStack
 55:      */
 56:     private static $_instance;
 57: 
 58:     /**
 59:      * Database object
 60:      *
 61:      * @var  cDb
 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:      * Constructor, sets some properties.
104:      */
105:     private function __construct() {
106:         global $cfg, $lang;
107:         $this->_oDb = cRegistry::getDb();
108:         $this->_aTab = $cfg['tab'];
109:         $this->_idLang = $lang;
110:     }
111: 
112:     /**
113:      * Returns a instance of ModRewriteUrlStack (singleton implementation)
114:      *
115:      * @return  ModRewriteUrlStack
116:      */
117:     public static function getInstance() {
118:         if (self::$_instance == NULL) {
119:             self::$_instance = new ModRewriteUrlStack();
120:         }
121:         return self::$_instance;
122:     }
123: 
124:     /**
125:      * Adds an url to the stack
126:      *
127:      * @param  string $url Url, like front_content.php?idcat=123...
128:      */
129:     public function add($url) {
130:         $url = ModRewrite::urlPreClean($url);
131:         if (isset($this->_aUrls[$url])) {
132:             return;
133:         }
134: 
135:         $aUrl = $this->_extractUrl($url);
136: 
137:         // cleanup parameter
138:         foreach ($aUrl['params'] as $p => $v) {
139:             if (!isset($this->_aConParams[$p])) {
140:                 unset($aUrl['params'][$p]);
141:             } else {
142:                 $aUrl['params'][$p] = (int) $v;
143:             }
144:         }
145: 
146:         // add language id, if not available
147:         if ((int) mr_arrayValue($aUrl['params'], 'lang') == 0) {
148:             $aUrl['params']['lang'] = $this->_idLang;
149:         }
150: 
151:         $sStackId = $this->_makeStackId($aUrl['params']);
152:         $this->_aUrls[$url] = $sStackId;
153:         $this->_aStack[$sStackId] = array('params' => $aUrl['params']);
154:     }
155: 
156:     /**
157:      * Returns the pretty urlparts (only category path an article name) of the
158:      * desired url.
159:      *
160:      * @param   string  Url, like front_content.php?idcat=123...
161:      *
162:      * @return  array   Assoziative array like
163:      * <code>
164:      * $arr['urlpath']
165:      * $arr['urlname']
166:      * </code>
167:      * @throws cDbException
168:      * @throws cInvalidArgumentException
169:      */
170:     public function getPrettyUrlParts($url) {
171:         $url = ModRewrite::urlPreClean($url);
172:         if (!isset($this->_aUrls[$url])) {
173:             $this->add($url);
174:         }
175: 
176:         $sStackId = $this->_aUrls[$url];
177:         if (!isset($this->_aStack[$sStackId]['urlpath'])) {
178:             $this->_chunkSetPrettyUrlParts($sStackId);
179:         }
180:         $aPretty = array(
181:             'urlpath' => $this->_aStack[$sStackId]['urlpath'],
182:             'urlname' => $this->_aStack[$sStackId]['urlname']
183:         );
184:         return $aPretty;
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:      * Extracts article or category related parameter from passed params array
208:      * and generates an identifier.
209:      *
210:      * @param   array   $aParams  Parameter array
211:      * @return  string  Composed stack id
212:      */
213:     private function _makeStackId(array $aParams) {
214:         # idcatart
215:         if ((int) mr_arrayValue($aParams, 'idart') > 0) {
216:             $sStackId = 'idart_' . $aParams['idart'] . '_lang_' . $aParams['lang'];
217:         } elseif ((int) mr_arrayValue($aParams, 'idartlang') > 0) {
218:             $sStackId = 'idartlang_' . $aParams['idartlang'];
219:         } elseif ((int) mr_arrayValue($aParams, 'idcatart') > 0) {
220:             $sStackId = 'idcatart_' . $aParams['idcatart'] . '_lang_' . $aParams['lang'];
221:         } elseif ((int) mr_arrayValue($aParams, 'idcat') > 0) {
222:             $sStackId = 'idcat_' . $aParams['idcat'] . '_lang_' . $aParams['lang'];
223:         } elseif ((int) mr_arrayValue($aParams, 'idcatlang') > 0) {
224:             $sStackId = 'idcatlang_' . $aParams['idcatlang'];
225:         } else {
226:             $sStackId = 'lang_' . $aParams['lang'];
227:         }
228:         return $sStackId;
229:     }
230: 
231:     /**
232:      * Main function to get the urlparts of urls.
233:      *
234:      * Composes the query by looping thru stored but non processed urls, executes
235:      * the query and adds the (urlpath and urlname) result to the stack.
236:      *
237:      * @param $sStackId
238:      *
239:      * @throws cDbException
240:      * @throws cInvalidArgumentException
241:      */
242:     private function _chunkSetPrettyUrlParts($sStackId) {
243:         // collect stack parameter to get urlpath and urlname
244:         $aStack = array();
245:         foreach ($this->_aStack as $stackId => $item) {
246:             if (!isset($item['urlpath'])) {
247:                 // pretty url is to create
248:                 $aStack[$stackId] = $item;
249:             }
250:         }
251: 
252:         // now, it's time to compose the where clause of the query
253:         $sWhere = '';
254:         foreach ($aStack as $stackId => $item) {
255: 
256:             if ($stackId == $sStackId) {
257:                 $aP = $item['params'];
258:                 if ((int)mr_arrayValue($aP, 'idart') > 0) {
259:                     $sWhere .= '(al.idart = ' . $aP['idart'] . ' AND al.idlang = ' . $aP['lang'] . ') OR ';
260:                 } elseif ((int)mr_arrayValue($aP, 'idartlang') > 0) {
261:                     $sWhere .= '(al.idartlang = ' . $aP['idartlang'] . ') OR ';
262:                 } elseif ((int)mr_arrayValue($aP, 'idcat') > 0) {
263:                     $sWhere .= '(cl.idcat = ' . $aP['idcat'] . ' AND cl.idlang = ' . $aP['lang'] . ' AND cl.startidartlang = al.idartlang) OR ';
264:                 } elseif ((int)mr_arrayValue($aP, 'idcatart') > 0) {
265:                     $sWhere .= '(ca.idcatart = ' . $aP['idcatart'] . ' AND ca.idart = al.idart AND al.idlang = ' . $aP['lang'] . ') OR ';
266:                 } elseif ((int)mr_arrayValue($aP, 'idcatlang') > 0) {
267:                     $sWhere .= '(cl.idcatlang = ' . $aP['idcatlang'] . ' AND cl.startidartlang = al.idartlang) OR ';
268:                 }
269:             }
270:         }
271:         if ($sWhere == '') {
272:             return;
273:         }
274:         $sWhere = cString::getPartOfString($sWhere, 0, -4);
275:         $sWhere = str_replace(' OR ', " OR \n", $sWhere);
276: 
277:         // compose query and execute it
278:         $sql = <<<SQL
279: SELECT
280:         al.idartlang, al.idart, al.idlang as lang, al.urlname, cl.idcatlang, cl.idcat,
281:         cl.urlpath, ca.idcatart
282: FROM
283:         {$this->_aTab['art_lang']} AS al, {$this->_aTab['cat_lang']} AS cl, {$this->_aTab['cat_art']} AS ca
284: WHERE
285:         al.idart = ca.idart AND
286:         ca.idcat = cl.idcat AND
287:         al.idlang = cl.idlang AND
288:         ($sWhere)
289: SQL;
290:         ModRewriteDebugger::add($sql, 'ModRewriteUrlStack->_chunkSetPrettyUrlParts() $sql');
291: 
292:         $aNewStack = array();
293: 
294:         // create array of fields, which are to reduce step by step from record set below
295:         $aFields = array('', 'idart', 'idartlang', 'idcatart', 'idcat');
296: 
297:         $this->_oDb->query($sql);
298:         while ($this->_oDb->nextRecord()) {
299:             $aRS = $this->_oDb->getRecord();
300: 
301:             // loop thru fields array
302:             foreach ($aFields as $field) {
303:                 if (isset($aRS[$field])) {
304:                     // reduce existing field
305:                     unset($aRS[$field]);
306:                 }
307:                 $rsStackID = $this->_makeStackId($aRS);
308:                 if (isset($aStack[$rsStackID])) {
309:                     // matching stack entry found, add urlpath and urlname to the new stack
310:                     $aNewStack[$rsStackID]['urlpath'] = $aRS['urlpath'];
311:                     $aNewStack[$rsStackID]['urlname'] = $aRS['urlname'];
312:                     break;
313:                 }
314:             }
315:         }
316:         ModRewriteDebugger::add($aNewStack, 'ModRewriteUrlStack->_chunkSetPrettyUrlParts() $aNewStack');
317: 
318:         // merge stack data
319:         $this->_aStack = array_merge($this->_aStack, $aNewStack);
320:     }
321: 
322: }
323: 
CMS CONTENIDO 4.10.1 API documentation generated by ApiGen 2.8.0