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

  • cCodeGeneratorAbstract
  • cCodeGeneratorFactory
  • cCodeGeneratorStandard
  • cContentTypeAbstract
  • cContentTypeAbstractTabbed
  • cContentTypeDate
  • cContentTypeFilelist
  • cContentTypeHead
  • cContentTypeHtml
  • cContentTypeHtmlhead
  • cContentTypeImg
  • cContentTypeImgdescr
  • cContentTypeImgeditor
  • cContentTypeLink
  • cContentTypeLinkdescr
  • cContentTypeLinkeditor
  • cContentTypeLinktarget
  • cContentTypeRaw
  • 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:  * @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:  * CONTENIDO standard code generator.
 19:  *
 20:  * @package Core
 21:  * @subpackage ContentType
 22:  */
 23: class cCodeGeneratorStandard extends cCodeGeneratorAbstract {
 24:     /**
 25:      * @var int
 26:      */
 27:     protected $_idtplcfg;
 28: 
 29:     /**
 30:      * Generates the code for a specific article (article for a client in a
 31:      * language).
 32:      *
 33:      * @see cCodeGeneratorAbstract::_generate()
 34:      *
 35:      * @param bool     $contype  [optional]
 36:      *                           Flag to enable/disable replacement of CMS_TAGS[]
 37:      * @param bool     $editable [optional]
 38:      * @param int|NULL $version  [optional]
 39:      *
 40:      * @return string
 41:      *         The generated code
 42:      *
 43:      * @throws cDbException
 44:      * @throws cException
 45:      * @throws cInvalidArgumentException
 46:      */
 47:     public function _generate($contype = true, $editable = true, $version = NULL) {
 48:         global $cfg, $code;
 49: 
 50:         $this->_cssData = '';
 51:         $this->_jsData = '';
 52:         $this->_tplName = '';
 53: 
 54:         cDebug::out("conGenerateCode($this->_idcat, $this->_idart, $this->_lang, $this->_client, $this->_layout);<br>");
 55: 
 56:         // set category article id
 57:         $idcatart = conGetCategoryArticleId($this->_idcat, $this->_idart);
 58: 
 59:         // set configuration for article
 60:         $this->_idtplcfg = $this->_getTemplateConfigurationId();
 61:         if (NULL === $this->_idtplcfg) {
 62:             $this->_processNoConfigurationError($idcatart);
 63:             return '0601';
 64:         }
 65: 
 66:         // list of configured container
 67:         $containerConfigurations = conGetContainerConfiguration($this->_idtplcfg);
 68: 
 69:         // set idlay and idmod array
 70:         $data = $this->_getTemplateData();
 71:         $idlay = $data['idlay'];
 72:         $idtpl = $data['idtpl'];
 73:         $this->_tplName = cString::cleanURLCharacters($data['name']);
 74: 
 75:         // list of used modules
 76:         $containerModules = conGetUsedModules($idtpl);
 77: 
 78:         // load layout code from file
 79:         $layoutInFile = new cLayoutHandler($idlay, '', $cfg, $this->_lang);
 80:         $this->_layoutCode = $layoutInFile->getLayoutCode();
 81:         $this->_layoutCode = cString::normalizeLineEndings($this->_layoutCode, "\n");
 82: 
 83:         $moduleHandler = new cModuleHandler();
 84: 
 85:         // create code for all containers
 86:         if ($idlay) {
 87:             cInclude('includes', 'functions.tpl.php');
 88:             $containerNumbers = tplGetContainerNumbersInLayout($idlay);
 89: 
 90:             // Initializing check arrays (CON-2706)
 91:             $loadedCSS = array();
 92:             $loadedJS = array();
 93: 
 94:             foreach ($containerNumbers as $containerNr) {
 95:                 // if there's no configured module in this container
 96:                 if (!isset($containerModules[$containerNr]) || !is_numeric($containerModules[$containerNr])) {
 97:                     // reset current module state and process empty container
 98:                     $this->_resetModule();
 99:                     $this->_processCmsContainer($containerNr);
100:                     continue;
101:                 }
102: 
103:                 $containerModuleId = $containerModules[$containerNr];
104:                 $oModule = new cApiModule($containerModuleId);
105:                 $module = $oModule->toArray();
106:                 if (false === $module) {
107:                     $module = array();
108:                 }
109: 
110:                 $this->_resetModule();
111: 
112:                 $this->_modulePrefix[] = '$cCurrentModule = ' . $containerModuleId . ';';
113:                 $this->_modulePrefix[] = '$cCurrentContainer = ' . $containerNr . ';';
114: 
115:                 $moduleHandler = new cModuleHandler($containerModuleId);
116:                 $input = '';
117:                 $this->_moduleCode = '';
118: 
119:                 // get contents of input and output from files and not from db
120:                 if ($moduleHandler->modulePathExists() == true) {
121:                     // do not execute faulty modules
122:                     // caution: if no module is bound to a container then idmod of $oModule is false
123:                     // caution: and as result error field is also empty
124:                     if ($oModule->get('error') === 'none' || $oModule->get('idmod') === false) {
125:                         $this->_moduleCode = $moduleHandler->readOutput();
126:                     } else {
127:                         continue;
128:                     }
129: 
130:                     // load css and js content of the js/css files
131:                     if ($moduleHandler->getFilesContent('css', 'css') !== false && !in_array($oModule->get('idmod'), $loadedCSS)) {
132:                         $this->_cssData .= $moduleHandler->getFilesContent('css', 'css') . PHP_EOL;
133:                         $loadedCSS[] = $oModule->get('idmod');
134:                     }
135: 
136:                     if ($moduleHandler->getFilesContent('js', 'js') !== false && !in_array($oModule->get('idmod'), $loadedJS)) {
137:                         $this->_jsData .= $moduleHandler->getFilesContent('js', 'js') . PHP_EOL;
138:                         $loadedJS[] = $oModule->get('idmod');
139:                     }
140: 
141:                     $input = $moduleHandler->readInput();
142:                 }
143: 
144:                 // CON-1536 strip comments from module code
145:                 // regex is not enough to correctly remove comments
146:                 // use php_strip_whitespace instead of writing own parser
147:                 // downside: php_strip_whitespace requires a file as parameter
148:                 $tmpFile = dirname(cRegistry::getBackendPath()) . '/' . $cfg['path']['temp'] . uniqid('code_gen_') . '.php';
149:                 if (cFileHandler::exists(dirname($tmpFile))
150:                     && cFileHandler::readable(dirname($tmpFile))
151:                     && cFileHandler::writeable(dirname($tmpFile))) {
152:                     if (false !== cFileHandler::write($tmpFile, $this->_moduleCode)) {
153:                         $this->_moduleCode = php_strip_whitespace($tmpFile);
154: 
155:                         // delete file
156:                         cFileHandler::remove($tmpFile);
157:                     }
158:                 }
159: 
160:                 // process CMS value tags
161:                 if (isset($containerConfigurations[$containerNr])) {
162:                     $containerCmsValues = $this->_processCmsValueTags($containerNr, $containerConfigurations[$containerNr]);
163:                 } else {
164:                     $containerCmsValues = '';
165:                 }
166: 
167:                 // add CMS value code to module prefix code
168:                 if ($containerCmsValues) {
169:                     $this->_modulePrefix[] = $containerCmsValues;
170:                 }
171: 
172:                 // process frontend debug
173:                 $this->_processFrontendDebug($containerNr, $module);
174: 
175:                 // replace new containers
176:                 $this->_processCmsContainer($containerNr);
177:             }
178:         }
179: 
180:         // find out what kind of CMS_... Vars are in use
181:         $a_content = $this->_getUsedCmsTypesData($editable, $version);
182: 
183:         // replace all CMS_TAGS[]
184:         if ($contype) {
185:             $this->_processCmsTags($a_content, true, $editable);
186:         }
187: 
188:         // add/replace title tag
189:         $this->_processCodeTitleTag();
190: 
191:         // add/replace meta tags
192:         $this->_processCodeMetaTags();
193: 
194:         // save the collected css/js data and save it under the template name
195:         // ([templatename].css , [templatename].js in cache dir
196:         $cssFile = '';
197:         if (cString::getStringLength($this->_cssData) > 0) {
198:             if (($myFileCss = $moduleHandler->saveContentToFile($this->_tplName, 'css', $this->_cssData)) !== false) {
199:                 $oHTML = new cHTML(array(
200:                     'rel' => 'stylesheet',
201:                     'type' => 'text/css',
202:                     'href' => $myFileCss
203:                 ));
204:                 $oHTML->setTag('link');
205:                 $cssFile = $oHTML->render();
206:             }
207:         }
208: 
209:         $jsFile = '';
210:         if (cString::getStringLength($this->_jsData) > 0) {
211:             if (($myFileJs = $moduleHandler->saveContentToFile($this->_tplName, 'js', $this->_jsData)) !== false) {
212:                 $jsFile = '<script src="' . $myFileJs . '" type="text/javascript"></script>';
213:             }
214:         }
215: 
216:         // add module CSS at {CSS} position, after title
217:         // or after opening head tag
218:         if (cString::findFirstPos($this->_layoutCode, '{CSS}') !== false) {
219:             $this->_layoutCode = cString::iReplaceOnce('{CSS}', $cssFile, $this->_layoutCode);
220:         } else if (!empty($cssFile)) {
221:             if (cString::findFirstPos($this->_layoutCode, '</title>') !== false) {
222:                 $matches = array();
223:                 if (preg_match_all("#(<head>.*?</title>)(.*?</head>)#si", $this->_layoutCode, $matches)) {
224:                     $this->_layoutCode = cString::iReplaceOnce($matches[1][0], $matches[1][0] . $cssFile . $matches[2][0], $this->_layoutCode);
225:                 }
226:             } else {
227:                 $this->_layoutCode = cString::iReplaceOnce('<head>', '<head>' . $cssFile, $this->_layoutCode);
228:             }
229:         }
230: 
231:         if (cString::findFirstPos($this->_layoutCode, '{REV}') !== false) {
232:             $this->_layoutCode = cString::iReplaceOnce('{REV}', ((int) getEffectiveSetting("ressource", "revision", 0)), $this->_layoutCode);
233:         }
234: 
235:         // add module JS at {JS} position
236:         // or before closing body tag if there is no {JS}
237:         if (cString::findFirstPos($this->_layoutCode, '{JS}') !== false) {
238:             $this->_layoutCode = cString::iReplaceOnce('{JS}', $jsFile, $this->_layoutCode);
239:         } else if (!empty($jsFile)) {
240:             $this->_layoutCode = cString::iReplaceOnce('</body>', $jsFile . '</body>', $this->_layoutCode);
241:         }
242: 
243:         if (cString::findFirstPos($this->_layoutCode, '{META}') !== false) {
244:             $this->_layoutCode = cString::iReplaceOnce('{META}', $this->_processCodeMetaTags(), $this->_layoutCode);
245:         } else {
246:             $this->_layoutCode = cString::iReplaceOnce('</head>', $this->_processCodeMetaTags() . '</head>', $this->_layoutCode);
247:         }
248: 
249:         if ($this->_feDebugOptions['general_information']) {
250:             $debugPrefix = '';
251: 
252:             $debugPrefix .= "<?php\nif (\$frontend_debug['general_information']) {\n";
253:             $debugPrefix .= "\techo(\"<!-- \\n\\n\");\n";
254: 
255:             $layout = new cApiLayout($idlay);
256:             $layouName = $layout->get('name');
257:             $debugPrefix .= "\techo(\"Layout: " . $layouName . " (" . $idlay . ")\\n\");\n";
258: 
259:             $debugPrefix .= "\techo(\"Template: " . $this->_tplName . " (" . $idtpl . ")\\n\");\n";
260: 
261:             $article = new cApiArticleLanguage($this->_idartlang);
262:             $catart = new cApiCategoryArticle();
263:             $cat = new cApiCategoryLanguage();
264:             $cat->loadByCategoryIdAndLanguageId($this->_idcat, $article->get('idlang'));
265:             $catart->loadByMany(array(
266:                 'idcat' => $cat->get('idcat'),
267:                 'idart' => $article->get('idart')
268:             ));
269:             $lang = new cApiLanguage($article->get('idlang'));
270:             $debugPrefix .= "\techo(\"Language: " . $lang->get('idlang') . " (" . $lang->get('name') . ")\\n\");\n";
271: 
272:             $debugPrefix .= "\techo(\"Category: " . $cat->get('idcat') . " (" . $cat->get('name') . ")\\n\");\n";
273: 
274:             $articleName = $article->get('title');
275:             $debugPrefix .= "\techo(\"Article: " . $articleName . " (catart = " . $catart->get('idcatart') . ", artlang = " . $this->_idartlang . ", art = " . $article->get('idart') . ")\\n\");\n";
276: 
277:             $debugPrefix .= "\techo(\"\\n--> \\n\");\n";
278:             $debugPrefix .= "}\n?>";
279: 
280:             $this->_layoutCode = $debugPrefix . $this->_layoutCode;
281:         }
282: 
283:         // save the generated code even if there are faulty modules
284:         // if one does not do so, a non existing cache file
285:         // will be tried to be loaded in frontend
286:         $this->_saveGeneratedCode($idcatart);
287: 
288:         return $this->_layoutCode;
289:     }
290: 
291:     /**
292:      * Will be invoked, if code generation wasn't able to find a
293:      * configured article or category.
294:      *
295:      * Creates a error message and writes this into the code cache.
296:      *
297:      * @param int $idcatart
298:      *         category article id
299:      *
300:      * @throws cDbException
301:      * @throws cInvalidArgumentException
302:      */
303:     protected function _processNoConfigurationError($idcatart) {
304:         cDebug::out('Neither CAT or ART are configured!<br><br>');
305: 
306:         $code = '<html><body>No code was created for this article in this category.</body><html>';
307:         $this->_saveGeneratedCode($idcatart, $code, false);
308:     }
309: 
310:     /**
311:      * Processes and adds or replaces title tag for an article.
312:      * Also calls the CEC 'Contenido.Content.CreateTitletag' for user defined title creation if none is given.
313:      *
314:      * @see cCodeGeneratorAbstract::_processCodeTitleTag()
315:      * @return string
316:      */
317:     protected function _processCodeTitleTag()
318:     {
319:         if ($this->_pageTitle == '') {
320:             cApiCecHook::setDefaultReturnValue($this->_pageTitle);
321:             $this->_pageTitle = cApiCecHook::executeAndReturn('Contenido.Content.CreateTitletag');
322:         }
323: 
324:         // define regular expressions
325:         $reHead  = '/<head>.*?<\/head>/is';
326:         $reTitle = '/<title>.*?<\/title>/is';
327: 
328:         // find head tags in layout code (case insensitive, search across linebreaks)
329:         $matches = [];
330:         $succ    = preg_match_all($reHead, $this->_layoutCode, $matches);
331: 
332:         // check if head tag has been found
333:         if (false !== $succ && count($matches) && isset($matches[0], $matches[0][0])) {
334:             // use first head tag found
335:             // by definition there must be no more than one head tag but user supplied markup might be invalid
336:             $headTag = $matches[0][0];
337: 
338:             // add or replace title
339:             if ($this->_pageTitle != '') {
340:                 $replaceTag = '{__TITLE__' . md5(rand() . time()) . '}';
341:                 $headCode   = preg_replace($reTitle, $replaceTag, $headTag, 1);
342:                 $pageTitle  = conHtmlentities($this->_pageTitle);
343:                 if (false !== cString::findFirstPos($headCode, $replaceTag)) {
344:                     $headCode = str_ireplace($replaceTag, "<title>$pageTitle</title>", $headCode);
345:                 } else {
346:                     $headCode = cString::iReplaceOnce('</head>', "<title>$pageTitle</title>\n</head>", $headCode);
347:                 }
348:             } else {
349:                 // remove empty title tags from head tag
350:                 $headCode = str_replace('<title></title>', '', $headTag);
351:             }
352: 
353:             // overwrite first head tag in original layout code
354:             $this->_layoutCode = preg_replace($reHead, $headCode, $this->_layoutCode, 1);
355:         }
356: 
357:         return $this->_layoutCode;
358:     }
359: 
360:     /**
361:      * Processes and adds or replaces all meta tags for an article.
362:      * Also calls the CEC 'Contenido.Content.CreateMetatags' for user defined
363:      * meta tags creation.
364:      *
365:      * @global array $encoding
366:      * @return string
367:      */
368:     protected function _processCodeMetaTags() {
369:         global $encoding;
370: 
371:         // get basic meta tags (from article & system)
372:         $metaTags = $this->_getBasicMetaTags();
373: 
374:         // process chain Contenido.Content.CreateMetatags to update meta tags
375:         $_cecIterator = cRegistry::getCecRegistry()->getIterator('Contenido.Content.CreateMetatags');
376:         if ($_cecIterator->count() > 0) {
377:             while (false !== $chainEntry = $_cecIterator->next()) {
378:                 $metaTags = $chainEntry->execute($metaTags);
379:             }
380:         }
381: 
382:         $sMetatags = '';
383: 
384:         foreach ($metaTags as $value) {
385: 
386:             // get meta tag keys
387:             $valueKeys = array_keys($value);
388:             $nameKey = 'name';
389:             foreach ($valueKeys as $key) {
390: 
391:                 if ($key != 'content')
392:                     $nameKey = $key;
393:             }
394: 
395:             // decode entities and htmlspecialchars, content will be converted
396:             // later using conHtmlSpecialChars() by render() function
397:             if (isset($value['content'])) {
398:                 $value['content'] = str_replace('"', '\"', (conHtmlEntityDecode(stripslashes($value['content']))));
399:             }
400: 
401:             // build up metatag string
402:             $oMetaTagGen = new cHTML();
403:             $oMetaTagGen->setTag('meta');
404:             $oMetaTagGen->updateAttributes($value);
405: 
406:             // HTML does not allow ID for meta tags
407:             $oMetaTagGen->removeAttribute('id');
408: 
409:             // check if metatag already exists
410:             $sPattern = '/(<meta(?:\s+)' . $nameKey . '(?:\s*)=(?:\s*)(?:\\"|\\\')(?:\s*)' . $value[$nameKey] . '(?:\s*)(?:\\"|\\\')(?:[^>]+)>\n?)/i';
411:             if (preg_match($sPattern, $this->_layoutCode, $aMatch)) {
412:                 // the meta tag is already specified in the layout
413:                 // replace it only if its attributes are not empty
414:                 $replace = true;
415:                 foreach ($value as $test) {
416:                     if ($test == '') {
417:                         $replace = false;
418:                         break;
419:                     }
420:                 }
421:                 if ($replace) {
422:                     $this->_layoutCode = str_replace($aMatch[1], $oMetaTagGen->render() . "\n", $this->_layoutCode);
423:                 }
424:             } else {
425:                 $sMetatags .= $oMetaTagGen->render() . "\n";
426:             }
427:         }
428: 
429:         return $sMetatags;
430:     }
431: 
432:     /**
433:      * Saves the generated code if layout flag is false and save flag is true.
434:      *
435:      * @param int    $idcatart
436:      *                               Category article id
437:      * @param string $code           [optional]
438:      *                               parameter for setting code manually instead of using the generated layout code
439:      * @param bool   $flagCreateCode [optional]
440:      *                               whether the create code flag in cat_art should be set or not (optional)
441:      * @throws cDbException
442:      * @throws cInvalidArgumentException
443:      * @global array $cfgClient
444:      */
445:     protected function _saveGeneratedCode($idcatart, $code = '', $flagCreateCode = true) {
446:         global $cfgClient;
447: 
448:         // Write code in the cache of the client. If the folder does not exist
449:         // create one.
450:         // do not write code cache into root directory of client
451:         if (cRegistry::getFrontendPath() === $cfgClient[$this->_client]['code']['path']) {
452:             return;
453:         }
454: 
455:         // parent directory must be named cache
456:         $directoryName = basename(dirname($cfgClient[$this->_client]['code']['path']));
457:         if ('cache' !== $directoryName) {
458:             // directory name is not cache -> abort
459:             return;
460:         }
461: 
462:         // CON-2113
463:         // Do not overwrite an existing .htaccess file to prevent misconfiguring permissions
464:         if ($this->_layout == false && $this->_save == true && isset($cfgClient[$this->_client]['code']['path'])) {
465:             if (false === is_dir($cfgClient[$this->_client]['code']['path'])) {
466:                 mkdir($cfgClient[$this->_client]['code']['path']);
467:                 @chmod($cfgClient[$this->_client]['code']['path'], cDirHandler::getDefaultPermissions());
468:             }
469: 
470:             if (true !== cFileHandler::exists($cfgClient[$this->_client]['code']['path'] . '.htaccess')) {
471:                 cFileHandler::write($cfgClient[$this->_client]['code']['path'] . '.htaccess', "Order Deny,Allow\nDeny from all\n");
472:             }
473: 
474:             if (true === is_dir($cfgClient[$this->_client]['code']['path'])) {
475:                 $fileCode = ($code == '')? $this->_layoutCode : $code;
476: 
477:                 $code = "<?php\ndefined('CON_FRAMEWORK') or die('Illegal call');\n\n?>\n" . $fileCode;
478:                 cFileHandler::write($cfgClient[$this->_client]['code']['path'] . $this->_client . '.' . $this->_lang . '.' . $idcatart . '.php', $code, false);
479: 
480:                 // Update create code flag
481:                 if ($flagCreateCode == true) {
482:                     $oCatArtColl = new cApiCategoryArticleCollection();
483:                     $oCatArtColl->setCreateCodeFlag($idcatart, 0);
484:                 }
485:             }
486:         }
487:     }
488: 
489:     /**
490:      * Collects and return basic meta tags/elements.
491:      *
492:      * @global array $encoding
493:      * @return array
494:      *         List of assozative meta tag values
495:      */
496:     protected function _getBasicMetaTags() {
497: 
498:         // collect all available meta tag entries with non empty values
499:         $metaTags = array();
500:         foreach (conGetAvailableMetaTagTypes() as $key => $value) {
501:             $metaValue = conGetMetaValue($this->_idartlang, $key);
502:             if (0 < cString::getStringLength($metaValue)) {
503:                 $metaTags[] = array(
504:                     $value['fieldname'] => $value['metatype'],
505:                     'content' => $metaValue
506:                 );
507:             }
508:         }
509: 
510:         // add generator meta tag
511:         // if the version is appended should be configurable
512:         // due to security reasons
513:         $generator = 'CMS CONTENIDO';
514:         $addVersion = true;
515:         if ($addVersion) {
516:             $cfg = cRegistry::getConfig();
517:             $aVersion = explode('.', CON_VERSION);
518:             $generator .= ' ' . $aVersion[0] . '.' . $aVersion[1];
519:         }
520:         $metaTags[] = array(
521:             'name' => 'generator',
522:             'content' => $generator
523:         );
524: 
525:         // add charset or content type meta tag
526:         global $encoding;
527:         if (getEffectiveSetting('generator', 'html5', 'false') == 'true') {
528:             $metaTags[] = array(
529:                 'charset' => $encoding[$this->_lang]
530:             );
531:         } elseif (getEffectiveSetting('generator', 'xhtml', 'false') == 'true') {
532:             $metaTags[] = array(
533:                 'http-equiv' => 'Content-Type',
534:                 'content' => 'application/xhtml+xml; charset=' . $encoding[$this->_lang]
535:             );
536:         } else {
537:             $metaTags[] = array(
538:                 'http-equiv' => 'Content-Type',
539:                 'content' => 'text/html; charset=' . $encoding[$this->_lang]
540:             );
541:         }
542: 
543:         // update (!) index setting of robots meta tag
544:         // the following value will not be changed
545:         // $index = (bool) $this->getArtLangObject()->get('searchable');
546:         // $metaTags = $this->_updateMetaRobots($metaTags, $index, NULL);
547: 
548:         return $metaTags;
549:     }
550: 
551:     /**
552:      * This method allows to set new values for the robots meta element.
553:      * If NULL is given for $index or $follow, existing settings are *not*
554:      * overwritten. If article should be indexed and followed, 'all' will be
555:      * set.
556:      *
557:      * @param array $metaTags
558:      *         array of meta elements to amend
559:      * @param bool|NULL $index
560:      *         if article should be indexed
561:      * @param bool|NULL $follow
562:      *         if links in article should be followed
563:      * @return array
564:      */
565:     protected function _updateMetaRobots(array $metaTags, $index, $follow) {
566: 
567:         // extract robots setting from current meta elements
568:         list($metaTags, $metaRobots) = $this->_extractMetaElement($metaTags, 'name', 'robots');
569: 
570:         if (is_null($metaRobots)) {
571:             // build new meta element if none could be found
572:             $metaRobots = array(
573:                 'name' => 'robots',
574:                 'content' => ''
575:             );
576:         } else {
577:             $content = array_map('trim', explode(',', $metaRobots['content']));
578:             // determine index from extracted element if given value is NULL
579:             if (is_null($index)) {
580:                 $index = (bool) (in_array('all', $content) || in_array('index', $content));
581:                 if (in_array('index', $content) || in_array('all', $content)) {
582:                     $index = true;
583:                 } else if (in_array('noindex', $content)) {
584:                     $index = true;
585:                 } else {
586:                     $index = NULL;
587:                 }
588:             }
589:             // determine follow from extracted element if given value is NULL
590:             if (is_null($follow)) {
591:                 if (in_array('follow', $content) || in_array('all', $content)) {
592:                     $follow = true;
593:                 } else if (in_array('nofollow', $content)) {
594:                     $follow = true;
595:                 } else {
596:                     $follow = NULL;
597:                 }
598:             }
599:         }
600: 
601:         // build and set new content for robots element
602:         $content = array();
603:         if (true === $index && true === $follow) {
604:             $content[] = 'all';
605:         } else {
606:             if (!is_null($index)) {
607:                 $content[] = $index? 'index' : 'noindex';
608:             }
609:             if (!is_null($follow)) {
610:                 $content[] = $follow? 'follow' : 'nofollow';
611:             }
612:         }
613:         $metaRobots['content'] = implode(',', $content);
614: 
615:         // add robots meta element
616:         $metaTags[] = $metaRobots;
617: 
618:         // what do you expect?
619:         return $metaTags;
620:     }
621: 
622:     /**
623:      * Extracts a meta element of type $type (either 'name' or 'http-equiv') and
624:      * name or HTTP header equivalent $nameOrEquiv from the given array of meta
625:      * elements.
626:      * Both, the reduced array of meta elements and the meta element to be
627:      * extracted are returned as an array. If the meta element to be extracted
628:      * could not be found, NULL will be returned in its place.
629:      *
630:      * @param array $metaTags
631:      * @param string $type
632:      *         either 'name' or 'http-equiv'
633:      * @param string $nameOrEquiv
634:      * @return array
635:      */
636:     protected function _extractMetaElement(array $metaTags, $type, $nameOrEquiv) {
637: 
638:         // prepare result structure
639:         $result = array(
640:             array(),
641:             NULL
642:         );
643: 
644:         // loop all given meta elements
645:         foreach ($metaTags as $metaTag) {
646:             if (!is_array($metaTag)) {
647:                 // skip $metaTag if it's no array
648:                 continue;
649:             } else if (!array_key_exists($type, $metaTag)) {
650:                 // add element to reduced array if it's of different type
651:                 array_push($result[0], $metaTag);
652:             } else if ($metaTag[$type] !== $nameOrEquiv) {
653:                 // add element to reduced array if it has different name
654:                 array_push($result[0], $metaTag);
655:             } else {
656:                 // set element as extracted element
657:                 $result[1] = $metaTag;
658:             }
659:         }
660: 
661:         // what do you expect?
662:         return $result;
663:     }
664: 
665: }
666: 
CMS CONTENIDO 4.10.0 API documentation generated by ApiGen 2.8.0