Overview

Packages

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

Classes

  • cCodeGeneratorAbstract
  • cCodeGeneratorFactory
  • cCodeGeneratorStandard
  • cContentTypeAbstract
  • cContentTypeAbstractTabbed
  • cContentTypeDate
  • cContentTypeFilelist
  • cContentTypeHead
  • cContentTypeHtml
  • cContentTypeHtmlhead
  • cContentTypeImg
  • cContentTypeImgdescr
  • cContentTypeImgeditor
  • cContentTypeLink
  • cContentTypeLinkdescr
  • cContentTypeLinkeditor
  • cContentTypeLinktarget
  • cContentTypeTeaser
  • cContentTypeText
  • cTypeGenerator
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * CONTENIDO code generator abstract class
  4:  *
  5:  * @package Core
  6:  * @subpackage ContentType
  7:  * @version SVN Revision $Rev:$
  8:  *
  9:  * @author Murat Purc <murat@purc.de>
 10:  * @copyright four for business AG <www.4fb.de>
 11:  * @license http://www.contenido.org/license/LIZENZ.txt
 12:  * @link http://www.4fb.de
 13:  * @link http://www.contenido.org
 14:  */
 15: 
 16: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 17: 
 18: /**
 19:  * CONTENIDO abstract code generator class.
 20:  *
 21:  * @package Core
 22:  * @subpackage ContentType
 23:  */
 24: abstract class cCodeGeneratorAbstract {
 25: 
 26:     /**
 27:      * CONTENIDO database instance
 28:      *
 29:      * @var cDb
 30:      */
 31:     protected $_db;
 32: 
 33:     /**
 34:      * Frontend debug options, see $frontend_debug in
 35:      * __FRONTEND_PATH__/data/config/config.php
 36:      *
 37:      * @var array
 38:      */
 39:     protected $_feDebugOptions = array();
 40: 
 41:     /**
 42:      * Collected CSS data for current template
 43:      *
 44:      * @var string
 45:      */
 46:     protected $_cssData = '';
 47: 
 48:     /**
 49:      * Collected JS data for current template
 50:      *
 51:      * @var string
 52:      */
 53:     protected $_jsData = '';
 54: 
 55:     /**
 56:      * Template name
 57:      *
 58:      * @var string
 59:      */
 60:     protected $_tplName = '';
 61: 
 62:     /**
 63:      * Category id
 64:      *
 65:      * @var int
 66:      */
 67:     protected $_idcat;
 68: 
 69:     /**
 70:      * Article id
 71:      *
 72:      * @var int
 73:      */
 74:     protected $_idart;
 75: 
 76:     /**
 77:      * Language id
 78:      *
 79:      * @var int
 80:      */
 81:     protected $_lang;
 82: 
 83:     /**
 84:      * Client id
 85:      *
 86:      * @var int
 87:      */
 88:     protected $_client;
 89: 
 90:     /**
 91:      * Flag to process layout
 92:      *
 93:      * @var bool
 94:      */
 95:     protected $_layout;
 96: 
 97:     /**
 98:      * Flag to persist generated code
 99:      *
100:      * @var bool
101:      */
102:     protected $_save;
103: 
104:     /**
105:      * Article language id
106:      *
107:      * @var int
108:      */
109:     protected $_idartlang;
110: 
111:     /**
112:      * Page title (generally from article language table)
113:      *
114:      * @var string
115:      */
116:     protected $_pageTitle;
117: 
118:     /**
119:      * Layout code.
120:      * Initially with container tags which will be replaced against module
121:      * outputs.
122:      *
123:      * @var string
124:      */
125:     protected $_layoutCode = '';
126: 
127:     /**
128:      * Module output code prefix
129:      *
130:      * @var array
131:      */
132:     protected $_modulePrefix = array();
133: 
134:     /**
135:      * Module output code
136:      *
137:      * @var string
138:      */
139:     protected $_moduleCode = '';
140: 
141:     /**
142:      * Module output code suffix
143:      *
144:      * @var array
145:      */
146:     protected $_moduleSuffix = array();
147: 
148:     /**
149:      * Module output code suffix
150:      *
151:      * @var cApiArticleLanguage
152:      */
153:     protected $_oArtLang;
154: 
155:     /**
156:      */
157:     public function __construct() {
158:         $this->_db = cRegistry::getDb();
159:     }
160: 
161:     /**
162:      * Setter for frontend debug options (see $frontend_debug in
163:      * __FRONTEND_PATH__/data/config/config.php
164:      * located in clients frontend directory)
165:      *
166:      * @param bool $debug
167:      */
168:     public function setFrontendDebugOptions(array $debugOptions) {
169:         $this->_feDebugOptions = $debugOptions;
170:     }
171: 
172:     /**
173:      * Generates the code for a specific article (article for a client in a
174:      * language).
175:      *
176:      * @param int $idcat
177:      * @param int $idart
178:      * @param int $lang
179:      * @param int $client
180:      * @param bool $layout
181:      * @param bool $save Flag to persist generated code
182:      * @param bool $contype Flag to enable/disable replacement of CMS_TAGS[]
183:      *
184:      * @throws cInvalidArgumentException if an article with the given idart and
185:      *         idlang can not be loaded
186:      * @return string Generated code or error code '0601' if no template
187:      *         configuration was found for category or article.
188:      */
189:     public function generate($idcat, $idart, $lang, $client, $layout = false, $save = true, $contype = true) {
190:         $this->_idcat = (int) $idcat;
191:         $this->_idart = (int) $idart;
192:         $this->_lang = (int) $lang;
193:         $this->_client = (int) $client;
194:         $this->_layout = (bool) $layout;
195:         $this->_save = (bool) $save;
196: 
197:         $this->_oArtLang = new cApiArticleLanguage();
198:         $this->_oArtLang->loadByArticleAndLanguageId($idart, $lang);
199:         if (!$this->_oArtLang->isLoaded()) {
200:             throw new cInvalidArgumentException('Couldn\'t load article language for idart=' . $idart . 'AND idlang=' . $lang);
201:         }
202: 
203:         $this->_idartlang = $this->_oArtLang->get('idartlang');
204:         $this->_pageTitle = stripslashes($this->_oArtLang->get('pagetitle'));
205: 
206:         return $this->_generate($contype);
207:     }
208: 
209:     /**
210:      * Generates the code for a specific article (article for a client in a
211:      * language).
212:      *
213:      * @param bool $contype Flag to enable/disable replacement of CMS_TAGS[]
214:      * @return string The generated code
215:      */
216:     abstract function _generate($contype = true);
217: 
218:     /**
219:      * Returns the template configuration id, either by configured article or by
220:      * configured category.
221:      *
222:      * @return int|NULL
223:      */
224:     protected function _getTemplateConfigurationId() {
225:         // Get configuration for article
226:         $idtplcfg = conGetTemplateConfigurationIdForArticle($this->_idart, $this->_idcat, $this->_lang, $this->_client);
227:         if (is_numeric($idtplcfg) && $idtplcfg != 0) {
228:             // Article is configured
229:             cDebug::out("configuration for article found: $idtplcfg<br><br>");
230:         } else {
231:             // Check whether category is configured
232:             $idtplcfg = conGetTemplateConfigurationIdForCategory($this->_idcat, $this->_lang, $this->_client);
233:             if (NULL !== $idtplcfg) {
234:                 // Category is configured
235:                 cDebug::out("configuration for category found: $idtplcfg<br><br>");
236:             }
237:         }
238: 
239:         return (is_numeric($idtplcfg)) ? $idtplcfg : NULL;
240:     }
241: 
242:     /**
243:      *
244:      * @param int $idcatart
245:      */
246:     abstract protected function _processNoConfigurationError($idcatart);
247: 
248:     /**
249:      * Returns array containing used layout, template and template name
250:      *
251:      * @global array $cfg
252:      * @return array Asooziative array like array('idlay' => (int), 'idtpl' =>
253:      *         (int), 'name' => (string))
254:      */
255:     protected function _getTemplateData() {
256:         global $cfg;
257: 
258:         // Get IDLAY and IDMOD array
259:         $sql = "SELECT
260:                     a.idlay AS idlay
261:                     , a.idtpl AS idtpl
262:                     , a.name AS name
263:                 FROM
264:                     `%s` AS a
265:                     , `%s` AS b
266:                 WHERE
267:                     b.idtplcfg = %d
268:                     AND b.idtpl = a.idtpl
269:                 ;";
270: 
271:         $sql = $this->_db->prepare($sql, $cfg['tab']['tpl'], $cfg['tab']['tpl_conf'], $this->_idtplcfg);
272:         $this->_db->query($sql);
273:         $this->_db->nextRecord();
274:         $data = $this->_db->toArray();
275: 
276:         if ($this->_layout !== false) {
277:             $data['idlay'] = $this->_layout;
278:         }
279: 
280:         cDebug::out("Using Layout: $data[idlay] and Template: $data[idtpl] for generation of code.<br><br>");
281: 
282:         return $data;
283:     }
284: 
285:     /**
286:      * Processes replacements of all existing CMS_...
287:      * tags within passed code
288:      *
289:      * @param array $contentList Assoziative list of CMS variables
290:      * @param bool $saveKeywords Flag to save collected keywords during
291:      *        replacement process.
292:      */
293:     protected function _processCmsTags($contentList, $saveKeywords = true) {
294:         // #####################################################################
295:         // NOTE: Variables below are required in included/evaluated content type
296:         // codes!
297:         global $db, $db2, $sess, $cfg, $code, $cfgClient, $encoding;
298: 
299:         // NOTE: Variables below are additionally required in included/evaluated
300:         // content type codes within backend edit mode!
301:         global $edit, $editLink, $belang;
302: 
303:         $idcat = $this->_idcat;
304:         $idart = $this->_idart;
305:         $lang = $this->_lang;
306:         $client = $this->_client;
307:         $idartlang = $this->_idartlang;
308: 
309:         if (!is_object($db2)) {
310:             $db2 = cRegistry::getDb();
311:         }
312:         // End: Variables required in content type codes
313:         // #####################################################################
314: 
315:         $match = array();
316:         $keycode = array();
317: 
318:         // NOTE: $a_content is used by included/evaluated content type codes
319:         // below
320:         $a_content = $contentList;
321: 
322:         // Select all cms_type entries
323:         $_typeList = array();
324:         $oTypeColl = new cApiTypeCollection();
325:         $oTypeColl->select();
326:         while ($oType = $oTypeColl->next()) {
327:             $_typeList[] = $oType->toObject();
328:         }
329: 
330:         // Replace all CMS_TAGS[]
331:         foreach ($_typeList as $_typeItem) {
332:             $key = strtolower($_typeItem->type);
333: 
334:             $type = $_typeItem->type;
335:             // Try to find all CMS_{type}[{number}] values, e. g. CMS_HTML[1]
336:             // $tmp = preg_match_all('/(' . $type . ')\[+([a-z0-9_]+)+\]/i',
337:             // $this->_layoutCode, $match);
338:             $tmp = preg_match_all('/(' . $type . '\[+(\d)+\])/i', $this->_layoutCode, $match);
339: 
340:             $a_[$key] = $match[0];
341: 
342:             $success = array_walk($a_[$key], 'extractNumber');
343: 
344:             $search = array();
345:             $replacements = array();
346: 
347:             $typeClassName = $this->_getContentTypeClassName($type);
348:             $typeCodeFile = $this->_getContentTypeCodeFilePathName($type);
349: 
350:             foreach ($a_[$key] as $val) {
351:                 if (class_exists($typeClassName)) {
352:                     // We have a class for the content type, use it
353:                     $tmp = $a_content[$_typeItem->type][$val];
354:                     $cTypeObject = new $typeClassName($tmp, $val, $a_content);
355:                     if (cRegistry::isBackendEditMode()) {
356:                         $tmp = $cTypeObject->generateEditCode();
357:                     } else {
358:                         $tmp = $cTypeObject->generateViewCode();
359:                     }
360:                 } else if (cFileHandler::exists($typeCodeFile)) {
361:                     // Include CMS type code file
362:                     include($typeCodeFile);
363:                 }
364: 
365:                 $search[$val] = sprintf('%s[%s]', $type, $val);
366:                 $replacements[$val] = $tmp;
367:                 $keycode[$type][$val] = $tmp;
368:             }
369: 
370:             $this->_layoutCode = str_ireplace($search, $replacements, $this->_layoutCode);
371:         }
372:     }
373: 
374:     /**
375:      * Processes title tag in page code (layout)
376:      */
377:     abstract protected function _processCodeTitleTag();
378: 
379:     /**
380:      * Processes all meta tags in page code (layout)
381:      */
382:     abstract protected function _processCodeMetaTags();
383: 
384:     /**
385:      * Replaces all container/module configuration tags (CMS_VALUE[n] values)
386:      * against their settings.
387:      *
388:      * @param int $containerNumber Container number
389:      * @param string $containerCfg A string being formatted like concatenated
390:      *        query
391:      *        parameter, e. g. param1=value1&param2=value2...
392:      *
393:      * @return string Concatenated PHP code containing CMS_VALUE variables and
394:      *         their values
395:      */
396:     protected function _processCmsValueTags($containerNumber, $containerCfg) {
397:         $containerCfgList = array();
398: 
399:         $containerCfg = preg_replace('/(&\$)/', '', $containerCfg);
400:         parse_str($containerCfg, $containerCfgList);
401:         /*
402:          * $tmp1 = preg_split('/&/', $containerCfg); foreach ($tmp1 as $key1 =>
403:          * $value1) { $tmp2 = explode('=', $value1); foreach ($tmp2 as $key2 =>
404:          * $value2) { $containerCfgList["$tmp2[0]"] = $tmp2[1]; } }
405:          */
406: 
407:         $CiCMS_Var = '$C' . $containerNumber . 'CMS_VALUE';
408:         $CiCMS_Values = array();
409: 
410:         foreach ($containerCfgList as $key3 => $value3) {
411:             // Convert special characters and escape backslashes!
412:             $tmp = conHtmlSpecialChars($value3);
413:             $tmp = str_replace('\\', '\\\\', $tmp);
414:             $CiCMS_Values[] = $CiCMS_Var . '[' . $key3 . '] = "' . $tmp . '"; ';
415:             $this->_moduleCode = str_replace("\$CMS_VALUE[$key3]", $tmp, $this->_moduleCode);
416:             $this->_moduleCode = str_replace("CMS_VALUE[$key3]", $tmp, $this->_moduleCode);
417:         }
418: 
419:         $this->_moduleCode = str_replace("CMS_VALUE", $CiCMS_Var, $this->_moduleCode);
420:         $this->_moduleCode = str_replace("\$" . $CiCMS_Var, $CiCMS_Var, $this->_moduleCode);
421:         $this->_moduleCode = preg_replace("/(CMS_VALUE\[)([0-9]*)(\])/i", '', $this->_moduleCode);
422: 
423:         return implode("\n", $CiCMS_Values);
424:     }
425: 
426:     /**
427:      * Extends container code by adding several debug features, if enabled and
428:      * configured.
429:      *
430:      * @param int $containerNumber Container number (The id attribute in container tag)
431:      * @param array $module Recordset as assoziative array of related module
432:      *        (container code)
433:      */
434:     protected function _processFrontendDebug($containerNumber, array $module) {
435:         global $containerinf;
436: 
437:         $data = $this->_getTemplateData();
438: 
439:         if (empty($this->_feDebugOptions)) {
440:             return;
441:         }
442: 
443:         $sFeDebug = '';
444:         if ($this->_feDebugOptions['container_display'] == true) {
445:             $this->_modulePrefix[] = 'if ($frontend_debug[\'container_display\']) echo "<!-- START CONTAINER ' . $containerinf[$data['idlay']][$containerNumber]['name'] . ' (' . $containerNumber . ') -->";';
446:         }
447: 
448:         if ($this->_feDebugOptions['module_display'] == true) {
449:             $this->_modulePrefix[] = 'if ($frontend_debug[\'module_display\']) echo "<!-- START MODULE ' . $module['name'] . ' (' . $module['idmod'] . ') -->";';
450:         }
451: 
452:         if ($this->_feDebugOptions['module_timing'] == true) {
453:             $this->_modulePrefix[] = '$modTime' . $containerNumber . ' = -getmicrotime(true);';
454:             $this->_moduleSuffix[] = '$modTime' . $containerNumber . ' += getmicrotime(true);';
455:         }
456: 
457:         if ($this->_feDebugOptions['module_display'] == true) {
458:             $this->_moduleSuffix[] = 'if ($frontend_debug[\'module_display\']) echo "<!-- END MODULE ' . $module['name'] . ' (' . $module['idmod'] . ')";';
459:             if ($this->_feDebugOptions['module_timing'] == true) {
460:                 $this->_moduleSuffix[] = 'if ($frontend_debug[\'module_timing\']) echo(" AFTER " . $modTime' . $containerNumber . ');';
461:             }
462:             $this->_moduleSuffix[] = 'if ($frontend_debug[\'module_display\']) echo " -->";';
463:         }
464:         if ($this->_feDebugOptions['container_display'] == true) {
465:             $this->_moduleSuffix[] = 'if ($frontend_debug[\'container_display\']) echo "<!-- END CONTAINER ' . $containerinf[$data['idlay']][$containerNumber]['name'] . ' (' . $containerNumber . ') -->";';
466:         }
467:     }
468: 
469:     /**
470:      * Replaces container tag in layout against the parsed container code
471:      * (module code).
472:      *
473:      * @param int $containerNumber Container number (The id attribute in container tag)
474:      */
475:     protected function _processCmsContainer($containerNumber) {
476:         $cmsContainer = "CMS_CONTAINER[$containerNumber]";
477: 
478:         // Replace new container (<container id="n"..>) against old one
479:         // (CMS_CONTAINER[n])
480:         $this->_layoutCode = preg_replace("/<container( +)id=\\\"$containerNumber\\\"(.*)>(.*)<\/container>/Uis", $cmsContainer, $this->_layoutCode);
481:         $this->_layoutCode = preg_replace("/<container( +)id=\\\"$containerNumber\\\"(.*)\/>/i", $cmsContainer, $this->_layoutCode);
482: 
483:         // Concatenate final container/module output code, but generate PHP code
484:         // only
485:         // if there is something to generate
486:         $modulePrefix = trim(implode("\n", $this->_modulePrefix));
487:         if (!empty($modulePrefix)) {
488:             $modulePrefix = "<?php\n" . $modulePrefix . "\n?>";
489:         }
490:         $moduleSuffix = trim(implode("\n", $this->_moduleSuffix));
491:         if (!empty($moduleSuffix)) {
492:             $moduleSuffix = "<?php\n" . $moduleSuffix . "\n?>";
493:         }
494:         $moduleOutput = $modulePrefix . $this->_moduleCode . $moduleSuffix;
495: 
496:         // Replace container (CMS_CONTAINER[n]) against the container code
497:         $this->_layoutCode = str_ireplace($cmsContainer, $moduleOutput, $this->_layoutCode);
498:         // $this->_layoutCode = addslashes($this->_layoutCode);
499:     }
500: 
501:     /**
502:      * Returns array of all CMS_...
503:      * vars being used by current article and language
504:      *
505:      * @return array like $arr[type][typeid] = value;
506:      */
507:     protected function _getUsedCmsTypesData() {
508:         global $cfg;
509: 
510:         $return = array();
511: 
512:         // Find out what kind of CMS_... Vars are in use
513:         $sql = "SELECT * FROM `%s` AS A, `%s` AS B, `%s` AS C
514:                 WHERE A.idtype = C.idtype AND A.idartlang = B.idartlang AND B.idart = %d AND B.idlang = %d";
515:         $sql = $this->_db->prepare($sql, $cfg['tab']['content'], $cfg['tab']['art_lang'], $cfg['tab']['type'], $this->_idart, $this->_lang);
516:         $this->_db->query($sql);
517:         while ($this->_db->nextRecord()) {
518:             $return[$this->_db->f('type')][$this->_db->f('typeid')] = $this->_db->f('value');
519:         }
520: 
521:         return $return;
522:     }
523: 
524:     /**
525:      * Resets module related variables
526:      */
527:     protected function _resetModule() {
528:         $this->_modulePrefix = array();
529:         $this->_moduleCode = '';
530:         $this->_moduleSuffix = array();
531:     }
532: 
533:     /**
534:      * Returns the classname for a content type.
535:      *
536:      * @param string $type Content type, e. g. CMS_HTMLHEAD
537:      *
538:      * @return string The classname e. g. cContentTypeHtmlhead for content type
539:      *         CMS_HTMLHEAD
540:      */
541:     protected function _getContentTypeClassName($type) {
542:         $typeClassName = 'cContentType' . ucfirst(strtolower(str_replace('CMS_', '', $type)));
543: 
544:         return $typeClassName;
545:     }
546: 
547:     /**
548:      * Returns the full path to the include file name of a content type.
549:      *
550:      * @param string $type Content type, e. g. CMS_HTMLHEAD
551:      *
552:      * @return string The full path e. g.
553:      *         {path_to_contenido_includes}/type/code/include.CMS_HTMLHEAD.code.php
554:      *         for content type CMS_HTMLHEAD
555:      */
556:     protected function _getContentTypeCodeFilePathName($type) {
557:         global $cfg;
558:         $typeCodeFile = cRegistry::getBackendPath() . $cfg['path']['includes'] . 'type/code/include.' . $type . '.code.php';
559: 
560:         return $typeCodeFile;
561:     }
562: 
563:     /**
564:      *
565:      * @return cApiArticleLanguage the artlang object
566:      */
567:     protected function getArtLangObject() {
568:         return $this->_oArtLang;
569:     }
570: }
571: 
CMS CONTENIDO 4.9.3 API documentation generated by ApiGen 2.8.0