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