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: /**
  4:  * CONTENIDO standard code generator
  5:  *
  6:  * @package Core
  7:  * @subpackage ContentType
  8:  * @version SVN Revision $Rev:$
  9:  *
 10:  * @author Murat Purc <murat@purc.de>
 11:  * @copyright four for business AG <www.4fb.de>
 12:  * @license http://www.contenido.org/license/LIZENZ.txt
 13:  * @link http://www.4fb.de
 14:  * @link http://www.contenido.org
 15:  */
 16: 
 17: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 18: 
 19: /**
 20:  * CONTENIDO standard code generator.
 21:  *
 22:  * @package Core
 23:  * @subpackage ContentType
 24:  */
 25: class cCodeGeneratorStandard extends cCodeGeneratorAbstract {
 26: 
 27:     /**
 28:      * {@inheritdoc}
 29:      */
 30:     public function _generate($contype = true) {
 31:         global $cfg, $code;
 32: 
 33:         $this->_cssData = '';
 34:         $this->_jsData = '';
 35:         $this->_tplName = '';
 36: 
 37:         cDebug::out("conGenerateCode($this->_idcat, $this->_idart, $this->_lang, $this->_client, $this->_layout);<br>");
 38: 
 39:         // Set category article id
 40:         $idcatart = conGetCategoryArticleId($this->_idcat, $this->_idart);
 41: 
 42:         // Set configuration for article
 43:         $this->_idtplcfg = $this->_getTemplateConfigurationId();
 44:         if (NULL === $this->_idtplcfg) {
 45:             $this->_processNoConfigurationError($idcatart);
 46:             return '0601';
 47:         }
 48: 
 49:         $a_c = conGetContainerConfiguration($this->_idtplcfg);
 50: 
 51:         // Set idlay and idmod array
 52:         $data = $this->_getTemplateData();
 53:         $idlay = $data['idlay'];
 54:         $idtpl = $data['idtpl'];
 55:         $this->_tplName = cApiStrCleanURLCharacters($data['name']);
 56: 
 57:         // List of used modules
 58:         $a_d = conGetUsedModules($idtpl);
 59: 
 60:         // Load layout code from file
 61:         $layoutInFile = new cLayoutHandler($idlay, '', $cfg, $this->_lang);
 62:         $this->_layoutCode = $layoutInFile->getLayoutCode();
 63:         $this->_layoutCode = cApiStrNormalizeLineEndings($this->_layoutCode, "\n");
 64: 
 65:         $moduleHandler = new cModuleHandler();
 66: 
 67:         // Create code for all containers
 68:         if ($idlay) {
 69:             cInclude('includes', 'functions.tpl.php');
 70:             tplPreparseLayout($idlay);
 71:             $tmp_returnstring = tplBrowseLayoutForContainers($idlay);
 72:             $a_container = explode('&', $tmp_returnstring);
 73: 
 74:             foreach ($a_container as $key => $value) {
 75:                 if (!isset($a_d[$value]) || !is_numeric($a_d[$value])) {
 76:                     // No configured module in this container
 77:                     // reset current module state and process empty container
 78:                     $this->_resetModule();
 79:                     $this->_processCmsContainer($value);
 80:                     continue;
 81:                 }
 82: 
 83:                 $oModule = new cApiModule($a_d[$value]);
 84:                 $module = $oModule->toArray();
 85:                 if (false === $module) {
 86:                     $module = array();
 87:                 }
 88: 
 89:                 $this->_resetModule();
 90: 
 91:                 $this->_modulePrefix[] = '$cCurrentModule = ' . $a_d[$value] . ';';
 92:                 $this->_modulePrefix[] = '$cCurrentContainer = ' . $value . ';';
 93: 
 94:                 $moduleHandler = new cModuleHandler($a_d[$value]);
 95:                 $input = '';
 96: 
 97:                 // Get the contents of input and output from files and not from
 98:                 // db-table
 99:                 if ($moduleHandler->modulePathExists() == true) {
100:                     $this->_moduleCode = $moduleHandler->readOutput();
101:                     // Load css and js content of the js/css files
102:                     if ($moduleHandler->getFilesContent('css', 'css') !== false) {
103:                         $this->_cssData .= $moduleHandler->getFilesContent('css', 'css');
104:                     }
105: 
106:                     if ($moduleHandler->getFilesContent('js', 'js') !== false) {
107:                         $this->_jsData .= $moduleHandler->getFilesContent('js', 'js');
108:                     }
109: 
110:                     $input = $moduleHandler->readInput();
111:                 }
112: 
113:                 $this->_moduleCode = $this->_moduleCode . "\n";
114: 
115:                 // Process CMS value tags
116:                 $containerCmsValues = $this->_processCmsValueTags($value, $a_c[$value]);
117: 
118:                 // Add CMS value code to module prefix code
119:                 if ($containerCmsValues) {
120:                     $this->_modulePrefix[] = $containerCmsValues;
121:                 }
122: 
123:                 // Process frontend debug
124:                 $this->_processFrontendDebug($value, $module);
125: 
126:                 // Replace new containers
127:                 $this->_processCmsContainer($value);
128:             }
129:         }
130: 
131:         // Find out what kind of CMS_... Vars are in use
132:         $a_content = $this->_getUsedCmsTypesData();
133: 
134:         // Replace all CMS_TAGS[]
135:         if ($contype) {
136:             $this->_processCmsTags($a_content, true);
137:         }
138: 
139:         // Add/replace title tag
140:         $this->_processCodeTitleTag();
141: 
142:         // Add/replace meta tags
143:         $this->_processCodeMetaTags();
144: 
145:         // Save the collected css/js data and save it under the template name
146:         // ([templatename].css , [templatename].js in cache dir
147:         $cssFile = '';
148:         if (strlen($this->_cssData) > 0) {
149:             if (($myFileCss = $moduleHandler->saveContentToFile($this->_tplName, 'css', $this->_cssData)) !== false) {
150:                 $cssFile = '<link rel="stylesheet" type="text/css" href="' . $myFileCss . '" />';
151:             }
152:         }
153: 
154:         $jsFile = '';
155:         if (strlen($this->_jsData) > 0) {
156:             if (($myFileJs = $moduleHandler->saveContentToFile($this->_tplName, 'js', $this->_jsData)) !== false) {
157:                 $jsFile = '<script src="' . $myFileJs . '" type="text/javascript"></script>';
158:             }
159:         }
160: 
161:         // // show toolbar with revisions of article This toolbar is only shown
162:         // in
163:         // // backend in edit mode if revision control is enabled
164:         // $revionsToolBar = $this->_revisionControl->getToolbar();
165:         // if (NULL !== $revionsToolBar) {
166:         // if (false !== strpos($this->_layoutCode, '<body>')) {
167:         // $this->_layoutCode = str_ireplace_once('<body>', '<body>' .
168:         // $revionsToolBar, $this->_layoutCode);
169:         // } else {
170:         // // TODO wo füg ich die dann ein?
171:         // // $this->_layoutCode .= $revionsToolBar;
172:         // }
173:         // }
174: 
175:         // add module CSS at {CSS} position, after title or after opening head
176:         // tag
177:         if (strpos($this->_layoutCode, '{CSS}') !== false) {
178:             $this->_layoutCode = cString::iReplaceOnce('{CSS}', $cssFile, $this->_layoutCode);
179:         } else if (!empty($cssFile)) {
180:             if (strpos($this->_layoutCode, '</title>') !== false) {
181:                 $this->_layoutCode = cString::iReplaceOnce('</title>', '</title>' . $cssFile, $this->_layoutCode);
182:             } else {
183:                 $this->_layoutCode = cString::iReplaceOnce('<head>', '<head>' . $cssFile, $this->_layoutCode);
184:             }
185:         }
186: 
187:         // add module JS at {JS} position or before closing body tag if there is
188:         // no {JS}
189:         if (strpos($this->_layoutCode, '{JS}') !== false) {
190:             $this->_layoutCode = cString::iReplaceOnce('{JS}', $jsFile, $this->_layoutCode);
191:         } else if (!empty($jsFile)) {
192:             $this->_layoutCode = cString::iReplaceOnce('</body>', $jsFile . '</body>', $this->_layoutCode);
193:         }
194: 
195:         if ($this->_feDebugOptions['general_information']) {
196:             $debugPrefix = '';
197: 
198:             $debugPrefix .= "<?php\nif (\$frontend_debug['general_information']) {\n";
199:             $debugPrefix .= "\techo(\"<!-- \\n\\n\");\n";
200: 
201:             $layout = new cApiLayout($idlay);
202:             $layouName = $layout->get('name');
203:             $debugPrefix .= "\techo(\"Layout: " . $layouName . " (" . $idlay . ")\\n\");\n";
204: 
205:             $debugPrefix .= "\techo(\"Template: " . $this->_tplName . " (" . $idtpl . ")\\n\");\n";
206: 
207:             $article = new cApiArticleLanguage($this->_idartlang);
208:             $catart = new cApiCategoryArticle();
209:             $cat = new cApiCategoryLanguage();
210:             $cat->loadByCategoryIdAndLanguageId($this->_idcat, $article->get('idlang'));
211:             $catart->loadByMany(array(
212:                 'idcat' => $cat->get('idcat'),
213:                 'idart' => $article->get('idart')
214:             ));
215:             $lang = new cApiLanguage($article->get('idlang'));
216:             $debugPrefix .= "\techo(\"Language: " . $lang->get('idlang') . " (" . $lang->get('name') . ")\\n\");\n";
217: 
218:             $debugPrefix .= "\techo(\"Category: " . $cat->get('idcat') . " (" . $cat->get('name') . ")\\n\");\n";
219: 
220:             $articleName = $article->get('title');
221:             $debugPrefix .= "\techo(\"Article: " . $articleName . " (catart = " . $catart->get('idcatart') . ", artlang = " . $this->_idartlang . ", art = " . $article->get('idart') . ")\\n\");\n";
222: 
223: 
224:             $debugPrefix .= "\techo(\"\\n--> \\n\");\n";
225:             $debugPrefix .= "}\n?>";
226: 
227:             $this->_layoutCode = $debugPrefix . $this->_layoutCode;
228:         }
229: 
230:         // Save the generated code
231:         $this->_saveGeneratedCode($idcatart);
232: 
233:         return $this->_layoutCode;
234:     }
235: 
236:     /**
237:      * Will be invoked, if code generation wasn't able to find a configured
238:      * article
239:      * or category.
240:      *
241:      * Creates a error message and writes this into the code cache.
242:      *
243:      * @param int $idcatart Category article id
244:      */
245:     protected function _processNoConfigurationError($idcatart) {
246:         cDebug::out('Neither CAT or ART are configured!<br><br>');
247: 
248:         $code = '<html><body>No code was created for this article in this category.</body><html>';
249:         $this->_saveGeneratedCode($idcatart, $code, false);
250:     }
251: 
252:     /**
253:      * Processes and adds or replaces title tag for an article.
254:      * Calls also the CEC 'Contenido.Content.CreateTitletag' for user defined
255:      * title creation.
256:      *
257:      * @see cCodeGeneratorAbstract::_processCodeTitleTag()
258:      * @return string
259:      */
260:     protected function _processCodeTitleTag() {
261:         if ($this->_pageTitle == '') {
262:             cApiCecHook::setDefaultReturnValue($this->_pageTitle);
263:             $this->_pageTitle = cApiCecHook::executeAndReturn('Contenido.Content.CreateTitletag');
264:         }
265: 
266:         // Add or replace title
267:         if ($this->_pageTitle != '') {
268:             $this->_layoutCode = preg_replace('/<title>.*?<\/title>/is', '{TITLE}', $this->_layoutCode, 1);
269:             if (strstr($this->_layoutCode, '{TITLE}')) {
270:                 $this->_layoutCode = str_ireplace('{TITLE}', '<title>' . $this->_pageTitle . '</title>', $this->_layoutCode);
271:             } else {
272:                 $this->_layoutCode = cString::iReplaceOnce('</head>', '<title>' . $this->_pageTitle . "</title>\n</head>", $this->_layoutCode);
273:             }
274:         } else {
275:             $this->_layoutCode = str_replace('<title></title>', '', $this->_layoutCode);
276:         }
277: 
278:         return $this->_layoutCode;
279:     }
280: 
281:     /**
282:      * Processes and adds or replaces all meta tags for an article.
283:      *
284:      * Calls also the CEC 'Contenido.Content.CreateMetatags' for user defined
285:      * meta tags creation.
286:      *
287:      * @global array $encoding
288:      */
289:     protected function _processCodeMetaTags() {
290:         global $encoding;
291: 
292:         // get basic meta tags (from article & system)
293:         $metaTags = $this->_getBasicMetaTags();
294: 
295:         // process chain Contenido.Content.CreateMetatags to update meta tags
296:         $_cecIterator = cRegistry::getCecRegistry()->getIterator('Contenido.Content.CreateMetatags');
297:         if ($_cecIterator->count() > 0) {
298:             while (false !== $chainEntry = $_cecIterator->next()) {
299:                 $metaTags = $chainEntry->execute($metaTags);
300:             }
301:         }
302: 
303:         $sMetatags = '';
304:         foreach ($metaTags as $value) {
305: 
306:             // get meta tag keys
307:             $valueKeys = array_keys($value);
308:             $nameKey = 'name';
309:             foreach ($valueKeys as $key) {
310: 
311:                 if ($key != 'content')
312:                     $nameKey = $key;
313:             }
314: 
315:             // decode entities and htmlspecialchars, content will be converted
316:             // later using conHtmlSpecialChars() by render() function
317:             if (isset($value['content'])) {
318:                 $value['content'] = conHtmlEntityDecode($value['content'], ENT_QUOTES, strtoupper($encoding[$this->_lang]));
319:                 $value['content'] = htmlspecialchars_decode($value['content'], ENT_QUOTES);
320:             }
321: 
322:             // build up metatag string
323:             $oMetaTagGen = new cHTML();
324:             $oMetaTagGen->setTag('meta');
325:             $oMetaTagGen->updateAttributes($value);
326: 
327:             // HTML does not allow ID for meta tags
328:             $oMetaTagGen->removeAttribute('id');
329: 
330:             // check if metatag already exists
331:             $sPattern = '/(<meta(?:\s+)' . $nameKey . '(?:\s*)=(?:\s*)(?:\\"|\\\')(?:\s*)' . $value[$nameKey] . '(?:\s*)(?:\\"|\\\')(?:[^>]+)>\n?)/i';
332:             if (preg_match($sPattern, $this->_layoutCode, $aMatch)) {
333:                 $this->_layoutCode = str_replace($aMatch[1], $oMetaTagGen->render() . "\n", $this->_layoutCode);
334:             } else {
335:                 $sMetatags .= $oMetaTagGen->render() . "\n";
336:             }
337:         }
338: 
339:         // add meta tags
340:         $this->_layoutCode = cString::iReplaceOnce('</head>', $sMetatags . '</head>', $this->_layoutCode);
341:     }
342: 
343:     /**
344:      * Saves the generated code (if layout flag is false and save flag is true)
345:      *
346:      * @global array $cfgClient
347:      * @param int $idcatart Category article id
348:      * @param string $code parameter for setting code manually instead of using
349:      *        the generated layout code
350:      * @param bool $flagCreateCode whether the create code flag in cat_art
351:      *        should be set or not (optional)
352:      */
353:     protected function _saveGeneratedCode($idcatart, $code = '', $flagCreateCode = true) {
354:         global $cfgClient;
355: 
356:         // Write code in the cache of the client. If the folder does not exist
357:         // create one.
358:         if ($this->_layout == false && $this->_save == true) {
359:             if (!is_dir($cfgClient[$this->_client]['code']['path'])) {
360:                 mkdir($cfgClient[$this->_client]['code']['path']);
361:                 @chmod($cfgClient[$this->_client]['code']['path'], 0777);
362:                 cFileHandler::write($cfgClient[$this->_client]['code']['path'] . '.htaccess', "Order Deny,Allow\nDeny from all\n");
363:             }
364: 
365:             $fileCode = ($code == '') ? $this->_layoutCode : $code;
366: 
367:             $code = "<?php\ndefined('CON_FRAMEWORK') or die('Illegal call');\n\n?>\n" . $fileCode;
368:             cFileHandler::write($cfgClient[$this->_client]['code']['path'] . $this->_client . '.' . $this->_lang . '.' . $idcatart . '.php', $code, false);
369: 
370:             // Update create code flag
371:             if ($flagCreateCode == true) {
372:                 $oCatArtColl = new cApiCategoryArticleCollection();
373:                 $oCatArtColl->setCreateCodeFlag($idcatart, 0);
374:             }
375:         }
376:     }
377: 
378:     /**
379:      * Collects and return basic meta tags/elements.
380:      *
381:      * @global array $encoding
382:      * @return array List of assozative meta tag values
383:      */
384:     protected function _getBasicMetaTags() {
385: 
386:         // collect all available meta tag entries with non empty values
387:         $metaTags = array();
388:         foreach (conGetAvailableMetaTagTypes() as $key => $value) {
389:             $metaValue = conGetMetaValue($this->_idartlang, $key);
390:             if (0 < strlen($metaValue)) {
391:                 $metaTags[] = array(
392:                     $value['fieldname'] => $value['metatype'],
393:                     'content' => $metaValue
394:                 );
395:             }
396:         }
397: 
398:         // add generator meta tag
399:         // if the version is appended should be configurable due to security
400:         // reasons
401:         $generator = 'CMS CONTENIDO';
402:         $addVersion = true;
403:         if ($addVersion) {
404:             $cfg = cRegistry::getConfig();
405:             $aVersion = explode('.', CON_VERSION);
406:             $generator .= ' ' . $aVersion[0] . '.' . $aVersion[1];
407:         }
408:         $metaTags[] = array(
409:             'name' => 'generator',
410:             'content' => $generator
411:         );
412: 
413:         // add charset or content type meta tag
414:         global $encoding;
415:         if (getEffectiveSetting('generator', 'html5', 'false') == 'true') {
416:             $metaTags[] = array(
417:                 'charset' => $encoding[$this->_lang]
418:             );
419:         } elseif (getEffectiveSetting('generator', 'xhtml', 'false') == 'true') {
420:             $metaTags[] = array(
421:                 'http-equiv' => 'Content-Type',
422:                 'content' => 'application/xhtml+xml; charset=' . $encoding[$this->_lang]
423:             );
424:         } else {
425:             $metaTags[] = array(
426:                 'http-equiv' => 'Content-Type',
427:                 'content' => 'text/html; charset=' . $encoding[$this->_lang]
428:             );
429:         }
430: 
431:         // update (!) index setting of robots meta tag
432:         // the follow value will not be changed
433:         // $index = (bool) $this->getArtLangObject()->get('searchable');
434:         // $metaTags = $this->_updateMetaRobots($metaTags, $index, NULL);
435: 
436:         return $metaTags;
437:     }
438: 
439:     /**
440:      * This method allows to set new values for the robots meta element.
441:      *
442:      * If NULL is given for $index or $follow, existing settings are *not*
443:      * overwritten. If article should be indexed and followed, 'all' will be
444:      * set.
445:      *
446:      * @param array $metaTags array of meta elements to amend
447:      * @param bool|NULL $index if article should be indexed
448:      * @param bool|NULL $follow if links in article should be followed
449:      * @return array
450:      */
451:     protected function _updateMetaRobots(array $metaTags, $index, $follow) {
452: 
453:         // extract robots setting from current meta elements
454:         list($metaTags, $metaRobots) = $this->_extractMetaElement($metaTags, 'name', 'robots');
455: 
456:         if (is_null($metaRobots)) {
457:             // build new meta element if none could be found
458:             $metaRobots = array(
459:                 'name' => 'robots',
460:                 'content' => ''
461:             );
462:         } else {
463:             $content = array_map('trim', explode(',', $metaRobots['content']));
464:             // determine index from extracted element if given value is NULL
465:             if (is_null($index)) {
466:                 $index = (bool) (in_array('all', $content) || in_array('index', $content));
467:                 if (in_array('index', $content) || in_array('all', $content)) {
468:                     $index = true;
469:                 } else if (in_array('noindex', $content)) {
470:                     $index = true;
471:                 } else {
472:                     $index = NULL;
473:                 }
474:             }
475:             // determine follow from extracted element if given value is NULL
476:             if (is_null($follow)) {
477:                 if (in_array('follow', $content) || in_array('all', $content)) {
478:                     $follow = true;
479:                 } else if (in_array('nofollow', $content)) {
480:                     $follow = true;
481:                 } else {
482:                     $follow = NULL;
483:                 }
484:             }
485:         }
486: 
487:         // build and set new content for robots element
488:         $content = array();
489:         if (true === $index && true === $follow) {
490:             $content[] = 'all';
491:         } else {
492:             if (!is_null($index)) {
493:                 $content[] = $index? 'index' : 'noindex';
494:             }
495:             if (!is_null($follow)) {
496:                 $content[] = $follow? 'follow' : 'nofollow';
497:             }
498:         }
499:         $metaRobots['content'] = implode(',', $content);
500: 
501:         // add robots meta element
502:         $metaTags[] = $metaRobots;
503: 
504:         // what do you expect?
505:         return $metaTags;
506:     }
507: 
508:     /**
509:      * Extracts a meta element of type $type (either 'name' or 'http-equiv') and
510:      * name or HTTP header equivalent $nameOrEquiv from the given array of meta
511:      * elements.
512:      *
513:      * Both, the reduced array of meta elements and the meta element to be
514:      * extracted are returned as an array. If the meta element to be extracted
515:      * could not be found, NULL will be returned in its place.
516:      *
517:      * @param array $metaTags
518:      * @param string $type either 'name' or 'http-equiv'
519:      * @param string $nameOrEquiv
520:      * @return array
521:      */
522:     protected function _extractMetaElement(array $metaTags, $type, $nameOrEquiv) {
523: 
524:         // prepare result structure
525:         $result = array(
526:             array(),
527:             NULL
528:         );
529: 
530:         // loop all given meta elements
531:         foreach ($metaTags as $metaTag) {
532:             if (!is_array($metaTag)) {
533:                 // skip $metaTag if it's no array
534:                 continue;
535:             } else if (!array_key_exists($type, $metaTag)) {
536:                 // add element to reduced array if it's of different type
537:                 array_push($result[0], $metaTag);
538:             } else if ($metaTag[$type] !== $nameOrEquiv) {
539:                 // add element to reduced array if it has different name
540:                 array_push($result[0], $metaTag);
541:             } else {
542:                 // set element as extracted element
543:                 $result[1] = $metaTag;
544:             }
545:         }
546: 
547:         // what do you expect?
548:         return $result;
549:     }
550: }
551: 
CMS CONTENIDO 4.9.1 API documentation generated by ApiGen 2.8.0