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:  * This file contains the cContentTypeTeaser class.
   5:  *
   6:  * @package Core
   7:  * @subpackage ContentType
   8:  * @author Timo Trautmann, Simon Sprankel
   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: cInclude('includes', 'functions.con.php');
  18: cInclude('includes', 'functions.api.images.php');
  19: 
  20: /**
  21:  * Content type CMS_TEASER which lets the editor select articles in various ways
  22:  * which are displayed as teasers.
  23:  *
  24:  * @package Core
  25:  * @subpackage ContentType
  26:  */
  27: class cContentTypeTeaser extends cContentTypeAbstractTabbed {
  28: 
  29:     /**
  30:      * Array which contains all avariable CMS_Types and its IDs in current
  31:      * CONTENIDO installation (described as hash [idtype => cmstypename]).
  32:      *
  33:      * @var array
  34:      */
  35:     private $_cmsTypes;
  36: 
  37:     /**
  38:      * Content types in this array will be completely ignored by CMS_TEASER.
  39:      *
  40:      * They won't be displayed in the frontend and they won't be shown as an
  41:      * option in the backend.
  42:      *
  43:      * @var array
  44:      */
  45:     private $_ignoreTypes = array();
  46: 
  47:     /**
  48:      * If CMS_TEASER tries to load one of the content types listed as the keys
  49:      * of this array it will load the value of that key instead.
  50:      *
  51:      * These won't be listed as an option in the backend either.
  52:      *
  53:      * @var array
  54:      */
  55:     private $_forwardTypes = array(
  56:         "CMS_EASYIMG" => "CMS_IMGEDITOR",
  57:         "CMS_IMG" => "CMS_IMGEDITOR",
  58:         "CMS_LINK" => "CMS_LINKEDITOR"
  59:     );
  60: 
  61:     /**
  62:      * Placeholders for labels in frontend.
  63:      *
  64:      * Important: This must be a static array!
  65:      *
  66:      * @var array
  67:      */
  68:     protected static $_translations = array(
  69:         "MORE"
  70:     );
  71: 
  72:     /**
  73:      * Variable for detecting current interation.
  74:      *
  75:      * @var int
  76:      */
  77:     protected $iteration = 0;
  78: 
  79:     /**
  80:      * Initialises class attributes and handles store events.
  81:      *
  82:      * @param string $rawSettings
  83:      *         the raw settings in an XML structure or as plaintext
  84:      * @param int $id
  85:      *         ID of the content type, e.g. 3 if CMS_DATE[3] is used
  86:      * @param array $contentTypes
  87:      *         array containing the values of all content types
  88:      */
  89:     public function __construct($rawSettings, $id, array $contentTypes) {
  90: 
  91:         // set props
  92:         $this->_type = 'CMS_TEASER';
  93:         $this->_prefix = 'teaser';
  94:         $this->_settingsType = self::SETTINGS_TYPE_XML;
  95:         $this->_formFields = array(
  96:             'teaser_title',
  97:             'teaser_category',
  98:             'teaser_count',
  99:             'teaser_style',
 100:             'teaser_manual',
 101:             'teaser_start',
 102:             'teaser_source_head',
 103:             'teaser_source_head_count',
 104:             'teaser_source_text',
 105:             'teaser_source_text_count',
 106:             'teaser_source_image',
 107:             'teaser_source_image_count',
 108:             'teaser_filter',
 109:             'teaser_sort',
 110:             'teaser_sort_order',
 111:             'teaser_character_limit',
 112:             'teaser_image_width',
 113:             'teaser_image_height',
 114:             'teaser_manual_art',
 115:             'teaser_image_crop',
 116:             'teaser_source_date',
 117:             'teaser_source_date_count'
 118:         );
 119: 
 120:         // call parent constructor
 121:         parent::__construct($rawSettings, $id, $contentTypes);
 122: 
 123:         // if form is submitted, store the current teaser settings
 124:         // notice: also check the ID of the content type (there could be more
 125:         // than one content type of the same type on the same page!)
 126:         if (isset($_POST[$this->_prefix . '_action']) && $_POST[$this->_prefix . '_action'] == 'store' && isset($_POST[$this->_prefix . '_id']) && (int) $_POST[$this->_prefix . '_id'] == $this->_id) {
 127:             $this->_storeSettings();
 128:         }
 129: 
 130:         $this->_setDefaultValues();
 131:     }
 132: 
 133:     /**
 134:      * Returns all translation strings for mi18n.
 135:      *
 136:      * @param array $translationStrings
 137:      *         translation strings
 138:      * @return array
 139:      *         updated translation string
 140:      */
 141:     public static function addModuleTranslations(array $translationStrings) {
 142:         foreach (self::$_translations as $value) {
 143:             $translationStrings[] = $value;
 144:         }
 145: 
 146:         return $translationStrings;
 147:     }
 148: 
 149:     /**
 150:      * Sets some default values for teaser in case that there is no value
 151:      * defined.
 152:      */
 153:     private function _setDefaultValues() {
 154:         // character limit is 120 by default
 155:         if ((int) $this->_settings['teaser_character_limit'] == 0) {
 156:             $this->_settings['teaser_character_limit'] = 120;
 157:         }
 158: 
 159:         // teaser cont is 6 by default
 160:         if ((int) $this->_settings['teaser_count'] == 0) {
 161:             $this->_settings['teaser_count'] = 6;
 162:         }
 163: 
 164:         // teasersort is creationdate by default
 165:         if (strlen($this->_settings['teaser_sort']) == 0) {
 166:             $this->_settings['teaser_sort'] = 'creationdate';
 167:         }
 168: 
 169:         // teaser style is liststyle by default
 170:         if (strlen($this->_settings['teaser_style']) == 0) {
 171:             $this->_settings['teaser_style'] = 'cms_teaser_slider.html';
 172:         }
 173: 
 174:         // teaser image width default
 175:         if ((int) $this->_settings['teaser_image_width'] == 0) {
 176:             $this->_settings['teaser_image_width'] = 100;
 177:         }
 178: 
 179:         // teaser image height default
 180:         if ((int) $this->_settings['teaser_image_height'] == 0) {
 181:             $this->_settings['teaser_image_height'] = 75;
 182:         }
 183: 
 184:         // cms type head default
 185:         if (strlen($this->_settings['teaser_source_head']) == 0) {
 186:             $this->_settings['teaser_source_head'] = 'CMS_HTMLHEAD';
 187:         }
 188: 
 189:         // cms type text default
 190:         if (strlen($this->_settings['teaser_source_text']) == 0) {
 191:             $this->_settings['teaser_source_text'] = 'CMS_HTML';
 192:         }
 193: 
 194:         // cms type image default
 195:         if (strlen($this->_settings['teaser_source_image']) == 0) {
 196:             $this->_settings['teaser_source_image'] = 'CMS_IMG';
 197:         }
 198: 
 199:         // cms type date default
 200:         if (strlen($this->_settings['teaser_source_date']) == 0) {
 201:             $this->_settings['teaser_source_date'] = 'CMS_DATE';
 202:         }
 203: 
 204:         // sort order of teaser articles
 205:         if (strlen($this->_settings['teaser_sort_order']) == 0) {
 206:             $this->_settings['teaser_sort_order'] = 'asc';
 207:         }
 208: 
 209:         // teaser image crop option
 210:         if (strlen($this->_settings['teaser_image_crop']) == 0 || $this->_settings['teaser_image_crop'] == 'false') {
 211:             $this->_settings['teaser_image_crop'] = 'false';
 212:         }
 213:     }
 214: 
 215:     /**
 216:      * Generates the code which should be shown if this content type is shown in
 217:      * the frontend.
 218:      *
 219:      * @return string
 220:      *         escaped HTML code which sould be shown if content type is shown in frontend
 221:      */
 222:     public function generateViewCode() {
 223:         $code = '";?><?php
 224:                     $teaser = new cContentTypeTeaser(\'%s\', %s, %s);
 225:                     echo $teaser->generateTeaserCode();
 226:                  ?><?php echo "';
 227:         // escape ' to avoid accidently ending the string in $code
 228:         $code = sprintf($code, str_replace('\'', '\\\'', $this->_rawSettings), $this->_id, 'array()');
 229: 
 230:         return $code;
 231:     }
 232: 
 233:     /**
 234:      * Function returns idarts of selected articles as array
 235:      *
 236:      * @return array
 237:      */
 238:     public function getConfiguredArticles() {
 239:         $articles = array();
 240:         $articles = $this->generateTeaserCode(true);
 241: 
 242:         return $articles;
 243:     }
 244: 
 245:     /**
 246:      * Function is called in edit- and viewmode in order to generate teasercode
 247:      * for output
 248:      *
 249:      * @param bool $returnAsArray [optional]
 250:      *         modeswitch betwwen template generation and returning result as array
 251:      * @return mixed
 252:      *         string of select box or array of articles
 253:      */
 254:     public function generateTeaserCode($returnAsArray = false) {
 255:         global $contenido;
 256: 
 257:         $articles = array();
 258: 
 259:         $template = new cTemplate();
 260:         // set title of teaser
 261:         $template->set('s', 'TITLE', $this->_settings['teaser_title']);
 262: 
 263:         // decide if it is a manual or category teaser
 264:         if ($this->_settings['teaser_manual'] == 'true' && count($this->_settings['teaser_manual_art']) > 0) {
 265:             $manualArts = $this->_settings['teaser_manual_art'];
 266:             if (!empty($manualArts) && !is_array($manualArts)) {
 267:                 $manualArts = array(
 268:                     $manualArts
 269:                 );
 270:             }
 271:             if (is_array($manualArts)) {
 272:                 $i = 0;
 273:                 // in manual case get all art to display and generate article
 274:                 // objects manually
 275:                 foreach ($manualArts as $idArt) {
 276:                     $article = new cApiArticleLanguage();
 277:                     $article->loadByArticleAndLanguageId($idArt, $this->_lang);
 278: 
 279:                     // try to fill teaser image
 280:                     if ($returnAsArray == false && $this->_fillTeaserTemplateEntry($article, $template)) {
 281:                         $i++;
 282:                         // break render, if teaser limit is reached
 283:                         if ($i == $this->_settings['teaser_count']) {
 284:                             break;
 285:                         }
 286:                     }
 287: 
 288:                     if ($returnAsArray == true && $this->_fillTeaserTemplateEntry($article, $template)) {
 289:                         array_push($articles, $article);
 290: 
 291:                         if ($i == $this->_settings['teaser_count']) {
 292:                             break;
 293:                         }
 294:                     }
 295:                 }
 296:             }
 297:         } else {
 298:             // in case of automatic teaser use class cArticleCollector
 299:             // for getting all arts in category
 300: 
 301:             $options = array(
 302:                 'lang' => $this->_lang,
 303:                 'client' => $this->_client,
 304:                 'idcat' => $this->_settings['teaser_category'],
 305:                 'order' => $this->_settings['teaser_sort'],
 306:                 'direction' => $this->_settings['teaser_sort_order'],
 307:                 'limit' => $this->_settings['teaser_count'],
 308:                 'start' => false,
 309:                 'offline' => false
 310:             );
 311: 
 312:             if ($this->_settings['teaser_start'] == 'true') {
 313:                 $options['start'] = true;
 314:             }
 315: 
 316:             $artCollector = new cArticleCollector($options);
 317: 
 318:             foreach ($artCollector as $article) {
 319: 
 320:                 $title =  trim($this->_getArtContent($article, $this->_settings['teaser_source_head'], $this->_settings['teaser_source_head_count']));
 321:                 $text =  trim($this->_getArtContent($article, $this->_settings['teaser_source_text'], $this->_settings['teaser_source_text_count']));
 322:                 $imageId = trim($this->_getArtContent($article, $this->_settings['teaser_source_image'], $this->_settings['teaser_source_image_count']));
 323: 
 324:                 if (!empty($title) || !empty($text) || !empty($imageId)) {
 325:                       if ($returnAsArray == true) {
 326:                          array_push($articles, $article);
 327:                     } else {
 328:                          $this->_fillTeaserTemplateEntry($article, $template);
 329:                     }
 330:                    }
 331:             }
 332:         }
 333: 
 334:         $code = '';
 335: 
 336:         // generate teasertemplate
 337:         if ($returnAsArray == false && file_exists($this->_cfgClient[$this->_client]['path']['frontend'] . 'templates/' . $this->_settings['teaser_style']) && count($template->Dyn_replacements) > 0) {
 338:             $code = $template->generate($this->_cfgClient[$this->_client]['path']['frontend'] . 'templates/' . $this->_settings['teaser_style'], true);
 339:             return $code;
 340:         } else if ($returnAsArray == true) {
 341:             return $articles;
 342:         }
 343:     }
 344: 
 345:     /**
 346:      * In edit and view mode this function fills teaser template with
 347:      * informations from a CONTENIDO article object.
 348:      *
 349:      * @param cApiArticleLanguage $article
 350:      *         CONTENIDO Article object
 351:      * @param cTemplate $template
 352:      *         CONTENIDO Template object (as reference)
 353:      * @return bool
 354:      *         success state of this operation
 355:      */
 356:     private function _fillTeaserTemplateEntry(cApiArticleLanguage $article, cTemplate &$template) {
 357:         global $contenido;
 358: 
 359:         // get necessary informations for teaser from articles use properties in
 360:         // a Settings for retrieval
 361:         $title = $this->_getArtContent($article, $this->_settings['teaser_source_head'], $this->_settings['teaser_source_head_count']);
 362:         $text = $this->_getArtContent($article, $this->_settings['teaser_source_text'], $this->_settings['teaser_source_text_count']);
 363:         $imageId = $this->_getArtContent($article, $this->_settings['teaser_source_image'], $this->_settings['teaser_source_image_count']);
 364:         $date = $this->_getArtContent($article, $this->_settings['teaser_source_date'], $this->_settings['teaser_source_date_count']);
 365: 
 366:         // check if CMS type is date before trying to parse it as date
 367:         if ('CMS_DATE' === $this->_settings['teaser_source_date']) {
 368:             $date = trim($date);
 369:             $date = new cContentTypeDate($date, 1, array('CMS_DATE'));
 370:             $date = $date->generateViewCode();
 371:         } else {
 372:             $date = trim(strip_tags($date));
 373:         }
 374: 
 375:         $idArt = $article->getField('idart');
 376:         $published = $article->getField('published');
 377:         $online = $article->getField('online');
 378: 
 379:         if ($online == 1 || $contenido) {
 380:             // teaserfilter defines strings which must be contained in text for
 381:             // display.
 382:             // if string is defined check if article contains this string and
 383:             // abort, if article does not contain this string
 384:             if ($this->_settings['teaser_filter'] != '') {
 385:                 $iPosText = strrpos(conHtmlEntityDecode($text), $this->_settings['teaser_filter']);
 386:                 $iPosHead = strrpos(conHtmlEntityDecode($title), $this->_settings['teaser_filter']);
 387:                 if (is_bool($iPosText) && !$iPosText && is_bool($iPosHead) && !$iPosHead) {
 388:                     return false;
 389:                 }
 390:             }
 391: 
 392:             // convert date to readable format
 393:             if (preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $published, $results)) {
 394:                 $published = $results[3] . '.' . $results[2] . '.' . $results[1];
 395:             }
 396: 
 397:             // strip tags in teaser text and cut it if it is to long
 398:             $title = trim(strip_tags($title));
 399:             $text = trim(strip_tags($text));
 400:             if (strlen($text) > $this->_settings['teaser_character_limit']) {
 401:                 $text = cString::trimAfterWord($text, $this->_settings['teaser_character_limit']) . '...';
 402:             }
 403: 
 404:             // try to get a teaser image directly from cms_img or try to extract
 405:             // if a content type is given, wich contains html
 406:             if ((int) $imageId > 0) {
 407:                 $image = $this->_getImage($imageId, $this->_settings['teaser_image_width'], $this->_settings['teaser_image_height'], $this->_settings['teaser_image_crop']);
 408:                 $template->set('d', 'IMAGE', $image['element']);
 409:                 $template->set('d', 'IMAGE_SRC', $image['src']);
 410:             } else if (strip_tags($imageId) != $imageId && strlen($imageId) > 0) {
 411:                 $image = $this->_extractImage($imageId);
 412:                 if (strlen($image['src']) > 0) {
 413:                     $template->set('d', 'IMAGE', $image['element']);
 414:                     $template->set('d', 'IMAGE_SRC', $image['src']);
 415:                 } else {
 416:                     $template->set('d', 'IMAGE', '');
 417:                     $template->set('d', 'IMAGE_SRC', '');
 418:                 }
 419:             } else {
 420:                 $template->set('d', 'IMAGE_SRC', '');
 421:                 $template->set('d', 'IMAGE', '');
 422:             }
 423: 
 424:             // strip all tags from manual teaser date
 425:             $date = strip_tags($date);
 426: 
 427:             // set generated values to teaser template
 428:             $template->set('d', 'TITLE', $title);
 429:             $template->set('d', 'TEXT', $text);
 430: 
 431:             $template->set('d', 'IDART', $idArt);
 432:             $template->set('d', 'ART_URL', 'front_content.php?idart=' . $idArt);
 433:             $template->set('d', 'PUBLISHED', $published);
 434:             $template->set('d', 'PUBLISHED_MANUAL', $date);
 435: 
 436:             if ($date != '') {
 437:                 $template->set('d', 'PUBLISHED_COMBINED', $date);
 438:             } else {
 439:                 $template->set('d', 'PUBLISHED_COMBINED', $published);
 440:             }
 441: 
 442:             foreach (self::$_translations as $translationString) {
 443:                 $template->set('d', $translationString, mi18n($translationString));
 444:             }
 445: 
 446:             if ($this->iteration == 0) {
 447:                 $template->set('d', 'ACTIVE', 'active');
 448:             } else {
 449:                 $template->set('d', 'ACTIVE', '');
 450:             }
 451:             $this->iteration++;
 452: 
 453:             $template->next();
 454:         }
 455: 
 456:         return true;
 457:     }
 458: 
 459:     /**
 460:      * Teaser allows to get a list of ids in which article content is searched
 461:      * in article like 1,2,5,6 the result with largest character count is
 462:      * returned
 463:      *
 464:      * @param cApiArticleLanguage $article
 465:      *         CONTENIDO article object
 466:      * @param string $contentTypeName
 467:      *         Name of Content type to extract informations from
 468:      * @param string $ids
 469:      *         list of ids to search in
 470:      * @return string
 471:      *         largest result of content
 472:      */
 473:     private function _getArtContent(cApiArticleLanguage &$article, $contentTypeName, $ids) {
 474:         $this->_initCmsTypes();
 475: 
 476:         $return = '';
 477:         // split ids, if there is only one id, array has only one place filled,
 478:         // that is also ok
 479:         foreach (explode(',', $ids) as $currentId) {
 480:             if ($this->_forwardTypes[$contentTypeName] != "") {
 481:                 $contentTypeName = $this->_forwardTypes[$contentTypeName];
 482:             }
 483:             $return .= ' ' . $article->getContent($contentTypeName, $currentId);
 484:         }
 485: 
 486:         return $return;
 487:     }
 488: 
 489:     /**
 490:      * When a HTML Code is given for a Teaser image try to find a image in this
 491:      * code and generate teaser image on that basis.
 492:      *
 493:      * @param string $content
 494:      *         HTML string to search image in
 495:      * @return string
 496:      *         img tag containing scaled image
 497:      */
 498:     private function _extractImage($content) {
 499:         $image = array();
 500: 
 501:         // search an image tag
 502:         $regEx = "/<img[^>]*?>.*?/i";
 503: 
 504:         $match = array();
 505:         preg_match($regEx, $content, $match);
 506: 
 507:         // if found extract its src content
 508:         $regEx = "/(src)(=)(['\"]?)([^\"']*)(['\"]?)/i";
 509:         $img = array();
 510:         preg_match($regEx, $match[0], $img);
 511: 
 512:         // check if this image lies in upload folder
 513:         $pos = strrpos($img[4], $this->_cfgClient[$this->_client]['upload']);
 514:         if (!is_bool($pos)) {
 515:             // if it is generate full internal path to image and scale it for
 516:             // display using class internal function getImage()
 517:             $file = $this->_cfgClient[$this->_client]['path']['frontend'] . $img[4];
 518:             $image = $this->_getImage($file, $this->_settings['teaser_image_width'], $this->_settings['teaser_image_height'], $this->_settings['teaser_image_crop'], true);
 519:         }
 520: 
 521:         return $image;
 522:     }
 523: 
 524:     /**
 525:      * Function gets path to an image of base of idupload in CONTENIDO,
 526:      * scales this image on basis of teaser settings and returns path to
 527:      * scaled image.
 528:      *
 529:      * It is also possible to give path to image directly, in this case set
 530:      * fourth parameter to true.
 531:      *
 532:      * @param int $image
 533:      *         idupl of image to use for teaser
 534:      * @param int $maxX
 535:      *         maximum image width
 536:      * @param int $maxY
 537:      *         maximum image height
 538:      * @param bool $isFile [optional]
 539:      *         in case of a direct file path retrival from database is not needed
 540:      * @return string
 541:      *         <img> tag contains scaled image
 542:      */
 543:     private function _getImage($image, $maxX, $maxY, $cropped, $isFile = false) {
 544:         $content = '';
 545:         $return = array();
 546: 
 547:         if ($cropped == 'true') {
 548:             $cropped = true;
 549:         } else {
 550:             $cropped = false;
 551:         }
 552: 
 553:         // check if there is a need to get image path
 554:         if ($isFile == false) {
 555:             $upload = new cApiUpload($image);
 556:             $dirname = $upload->get('dirname');
 557:             $filename = $upload->get('filename');
 558:             if (!empty($dirname) && !empty($filename)) {
 559:                 $teaserImage = $this->_cfgClient[$this->_client]['path']['frontend'] . 'upload/' . $dirname . $filename;
 560:             }
 561:         } else {
 562:             $teaserImage = $image;
 563:         }
 564: 
 565:         // scale image if exists and return it
 566:         if (file_exists($teaserImage)) {
 567:             // Scale Image using cApiImgScale
 568:             $imgSrc = cApiImgScale($teaserImage, $maxX, $maxY, $cropped);
 569: 
 570:             if ($this->_useXHTML == 'true') {
 571:                 $letter = ' /';
 572:             } else {
 573:                 $letter = '';
 574:             }
 575: 
 576:             // Put Image into the teasertext
 577:             $content = '<img alt="" src="' . $imgSrc . '" class="teaser_image"' . $letter . '>' . $content;
 578:         }
 579: 
 580:         $return['element'] = $content;
 581:         $return['src'] = $imgSrc;
 582: 
 583:         return $return;
 584:     }
 585: 
 586:     /**
 587:      * Generates the code which should be shown if this content type is edited.
 588:      *
 589:      * @return string
 590:      *         escaped HTML code which should be shown if content type is edited
 591:      */
 592:     public function generateEditCode() {
 593:         $this->_initCmsTypes();
 594: 
 595:         $template = new cTemplate();
 596:         // Set some values into javascript for a better handling
 597:         $template->set('s', 'ID', $this->_id);
 598:         $template->set('s', 'IDARTLANG', $this->_idArtLang);
 599:         $template->set('s', 'FIELDS', "'" . implode("','", $this->_formFields) . "'");
 600: 
 601:         $templateTabs = new cTemplate();
 602:         $templateTabs->set('s', 'PREFIX', $this->_prefix);
 603: 
 604:         // create code for general tab
 605:         $templateTabs->set('d', 'TAB_ID', 'general');
 606:         $templateTabs->set('d', 'TAB_CLASS', 'general');
 607:         $templateTabs->set('d', 'TAB_CONTENT', $this->_generateTabGeneral());
 608:         $templateTabs->next();
 609: 
 610:         // create code for advanced tab
 611:         $templateTabs->set('d', 'TAB_ID', 'advanced');
 612:         $templateTabs->set('d', 'TAB_CLASS', 'advanced');
 613:         $templateTabs->set('d', 'TAB_CONTENT', $this->_generateTabAdvanced());
 614:         $templateTabs->next();
 615: 
 616:         // create code for manual tab
 617:         $templateTabs->set('d', 'TAB_ID', 'manual');
 618:         $templateTabs->set('d', 'TAB_CLASS', 'manual');
 619:         $templateTabs->set('d', 'TAB_CONTENT', $this->_generateTabManual());
 620:         $templateTabs->next();
 621: 
 622:         $codeTabs = $templateTabs->generate($this->_cfg['path']['contenido'] . 'templates/standard/template.cms_abstract_tabbed_edit_tabs.html', true);
 623: 
 624:         // construct the top code of the template
 625:         $templateTop = new cTemplate();
 626:         $templateTop->set('s', 'ICON', 'images/isstart0.gif');
 627:         $templateTop->set('s', 'ID', $this->_id);
 628:         $templateTop->set('s', 'PREFIX', $this->_prefix);
 629:         $templateTop->set('s', 'HEADLINE', i18n('Teaser settings'));
 630:         $codeTop = $templateTop->generate($this->_cfg['path']['contenido'] . 'templates/standard/template.cms_abstract_tabbed_edit_top.html', true);
 631: 
 632:         // define the available tabs
 633:         $tabMenu = array(
 634:             'general' => i18n('Automatic'),
 635:             'advanced' => i18n('Manual'),
 636:             'manual' => i18n('Settings')
 637:         );
 638: 
 639:         // construct the bottom code of the template
 640:         $templateBottom = new cTemplate();
 641:         $templateBottom->set('s', 'PATH_FRONTEND', $this->_cfgClient[$this->_client]['path']['htmlpath']);
 642:         $templateBottom->set('s', 'ID', $this->_id);
 643:         $templateBottom->set('s', 'PREFIX', $this->_prefix);
 644:         $templateBottom->set('s', 'IDARTLANG', $this->_idArtLang);
 645:         $templateBottom->set('s', 'FIELDS', "'" . implode("','", $this->_formFields) . "'");
 646:         $templateBottom->set('s', 'SETTINGS', json_encode($this->_settings));
 647:         $templateBottom->set('s', 'JS_CLASS_SCRIPT', $this->_cfg['path']['contenido_fullhtml'] . 'scripts/content_types/cmsTeaser.js');
 648:         $templateBottom->set('s', 'JS_CLASS_NAME', 'Con.cContentTypeTeaser');
 649:         $codeBottom = $templateBottom->generate($this->_cfg['path']['contenido'] . 'templates/standard/template.cms_abstract_tabbed_edit_bottom.html', true);
 650: 
 651:         // construct the whole template code
 652:         $code = $this->generateViewCode();
 653:         $code .= $this->_encodeForOutput($codeTop);
 654:         $code .= $this->_generateTabMenuCode($tabMenu);
 655:         $code .= $this->_encodeForOutput($codeTabs);
 656:         $code .= $this->_generateActionCode();
 657:         $code .= $this->_encodeForOutput($codeBottom);
 658: 
 659:         return $code;
 660:     }
 661: 
 662:     /**
 663:      * Gets all currenty avariable content types and their ids
 664:      * from database and store it into class variable aCMSTypes.
 665:      * Because this information is used multiple times, this causes a better
 666:      * performance than gettting it seperately
 667:      */
 668:     private function _initCmsTypes() {
 669:         if (!empty($this->_cmsTypes)) {
 670:             return;
 671:         }
 672: 
 673:         $this->_cmsTypes = array();
 674: 
 675:         $sql = 'SELECT * FROM ' . $this->_cfg['tab']['type'] . ' ORDER BY type';
 676:         $db = cRegistry::getDb();
 677:         $db->query($sql);
 678:         while ($db->nextRecord()) {
 679:             // we do not want certain content types
 680:             if (in_array($db->f('type'), $this->_ignoreTypes)) {
 681:                 continue;
 682:             }
 683:             $this->_cmsTypes[$db->f('idtype')] = $db->f('type');
 684:         }
 685:     }
 686: 
 687:     /**
 688:      * Generates code for the general tab in which various settings can be made.
 689:      *
 690:      * @return string
 691:      *         the code for the general tab
 692:      */
 693:     private function _generateTabGeneral() {
 694:         // define a wrapper which contains the whole content of the general tab
 695:         $wrapper = new cHTMLDiv();
 696:         $wrapperContent = array();
 697: 
 698:         // $wrapperContent[] = new cHTMLParagraph(i18n('General settings'),
 699:         // 'head_sub');
 700:         $wrapperContent[] = new cHTMLLabel(i18n('Teaser title'), 'teaser_title_' . $this->_id);
 701:         $wrapperContent[] = new cHTMLTextbox('teaser_title_' . $this->_id, $this->_settings['teaser_title'], '', '', 'teaser_title_' . $this->_id);
 702:         $wrapperContent[] = new cHTMLLabel(i18n('Source category'), 'teaser_category_' . $this->_id);
 703:         $wrapperContent[] = buildCategorySelect('teaser_category_' . $this->_id, $this->_settings['teaser_category'], 0);
 704:         $wrapperContent[] = new cHTMLLabel(i18n('Number of articles'), 'teaser_count_' . $this->_id);
 705:         $wrapperContent[] = $this->_generateCountSelect();
 706: 
 707:         $wrapperContent[] = new cHTMLLabel(i18n("Include start article"), 'teaser_start_' . $this->_id);
 708:         $wrapperContent[] = new cHTMLCheckbox('teaser_start_' . $this->_id, '', 'teaser_start_' . $this->_id, ($this->_settings['teaser_start'] == 'true'));
 709: 
 710:         $wrapperContent[] = new cHTMLLabel(i18n("Teaser sort"), 'teaser_sort_' . $this->_id);
 711:         $wrapperContent[] = $this->_generateSortSelect();
 712:         $wrapperContent[] = new cHTMLLabel(i18n("Sort order"), 'teaser_sort_order_' . $this->_id);
 713:         $wrapperContent[] = $this->_generateSortOrderSelect();
 714: 
 715:         $wrapper->setContent($wrapperContent);
 716:         return $wrapper->render();
 717:     }
 718: 
 719:     /**
 720:      * Generats a select box for setting number of articles which should be
 721:      * displayed in teaser as a maximum.
 722:      *
 723:      * Only important in editmode.
 724:      *
 725:      * @return string
 726:      *         html string of select box
 727:      */
 728:     private function _generateCountSelect() {
 729:         $htmlSelect = new cHTMLSelectElement('teaser_count_' . $this->_id, '', 'teaser_count_' . $this->_id);
 730: 
 731:         // set please chose option element
 732:         $htmlSelectOption = new cHTMLOptionElement(i18n('Please choose'), '', true);
 733:         $htmlSelect->appendOptionElement($htmlSelectOption);
 734: 
 735:         // generate a select box containing count 1 to 20 for maximum teaser
 736:         // count
 737:         for ($i = 1; $i <= 20; $i++) {
 738:             $htmlSelectOption = new cHTMLOptionElement($i, $i, false);
 739:             $htmlSelect->appendOptionElement($htmlSelectOption);
 740:         }
 741: 
 742:         // set default value
 743:         $htmlSelect->setDefault($this->_settings['teaser_count']);
 744: 
 745:         return $htmlSelect->render();
 746:     }
 747: 
 748:     /**
 749:      * Generats a select box for setting teaser style.
 750:      *
 751:      * Currently four default teaser templates are supported but any number of
 752:      * user templates can be defined as settings of type "cms_teaser" having a
 753:      * label as name and a filename as value.
 754:      *
 755:      * The default templates are:
 756:      * - Slider style (cms_teaser_slider.html)
 757:      * - Image style (cms_teaser_image.html)
 758:      * - Text style (cms_teaser_text.html)
 759:      * - Blog style (cms_teaser_blog.html)
 760:      *
 761:      * @return string
 762:      *         html string of select box
 763:      */
 764:     private function _generateStyleSelect() {
 765:         $htmlSelect = new cHTMLSelectElement('teaser_style_' . $this->_id, '', 'teaser_style_' . $this->_id);
 766: 
 767:         // set please chose option element
 768:         $htmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
 769:         $htmlSelect->appendOptionElement($htmlSelectOption);
 770: 
 771:         // set other avariable options manually
 772:         $htmlSelectOption = new cHTMLOptionElement(i18n("Slider style"), 'cms_teaser_slider.html', false);
 773:         $htmlSelect->appendOptionElement($htmlSelectOption);
 774: 
 775:         $htmlSelectOption = new cHTMLOptionElement(i18n("Image style"), 'cms_teaser_image.html', false);
 776:         $htmlSelect->appendOptionElement($htmlSelectOption);
 777: 
 778:         $htmlSelectOption = new cHTMLOptionElement(i18n("Text style"), 'cms_teaser_text.html', false);
 779:         $htmlSelect->appendOptionElement($htmlSelectOption);
 780: 
 781:         $htmlSelectOption = new cHTMLOptionElement(i18n("Blog style"), 'cms_teaser_blog.html', false);
 782:         $htmlSelect->appendOptionElement($htmlSelectOption);
 783: 
 784:         $additionalOptions = getEffectiveSettingsByType('cms_teaser');
 785:         foreach ($additionalOptions as $sLabel => $sTemplate) {
 786:             $htmlSelectOption = new cHTMLOptionElement($sLabel, $sTemplate, false);
 787:             $htmlSelect->appendOptionElement($htmlSelectOption);
 788:         }
 789: 
 790:         // set default value
 791:         $htmlSelect->setDefault($this->_settings['teaser_style']);
 792: 
 793:         return $htmlSelect->render();
 794:     }
 795: 
 796:     /**
 797:      * Teaser gets informations from other articles and their content typs.
 798:      *
 799:      * Function builds a select box in which coresponding cms type can be
 800:      * selected after that a text box is rendered for setting id for this
 801:      * content type to get informations from.
 802:      *
 803:      * This function is used three times for source defintion of headline,
 804:      * text and teaserimage.
 805:      *
 806:      * @param string $selectName
 807:      *         name of input elements
 808:      * @param string $selected
 809:      *         value of select box which is selected
 810:      * @param string $value
 811:      *         current value of text box
 812:      * @return string
 813:      *         html string of select box
 814:      */
 815:     private function _generateTypeSelect($selectName, $selected, $value) {
 816:         // make sure that the ID is at the end of the form field name
 817:         $inputName = str_replace('_' . $this->_id, '_count_' . $this->_id, $selectName);
 818:         // generate textbox for content type id
 819:         $htmlInput = new cHTMLTextbox($inputName, $value, '', '', $inputName, false, '', '', 'teaser_type_count');
 820: 
 821:         // generate content type select
 822:         $htmlSelect = new cHTMLSelectElement($selectName, '', $selectName);
 823:         $htmlSelect->setClass('teaser_type_select');
 824: 
 825:         $htmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
 826:         $htmlSelect->addOptionElement(0, $htmlSelectOption);
 827: 
 828:         // use $this->_cmsTypes as basis for this select box which contains all
 829:         // avariable content types in system
 830:         foreach ($this->_cmsTypes as $key => $value) {
 831:             $htmlSelectOption = new cHTMLOptionElement($value, $value, false);
 832:             $htmlSelect->addOptionElement($key, $htmlSelectOption);
 833:         }
 834: 
 835:         // set default value
 836:         $htmlSelect->setDefault($selected);
 837: 
 838:         return $htmlSelect->render() . $htmlInput->render();
 839:     }
 840: 
 841:     /**
 842:      * Generates code for the advanced tab in which various advanced settings
 843:      * can be made.
 844:      *
 845:      * @return string
 846:      *         the code for the advanced tab
 847:      */
 848:     private function _generateTabAdvanced() {
 849:         // define a wrapper which contains the whole content of the advanced tab
 850:         $wrapper = new cHTMLDiv();
 851:         $wrapperContent = array();
 852: 
 853:         // $wrapperContent[] = new cHTMLParagraph(i18n('Manual teaser
 854:         // settings'), 'head_sub');
 855:         $wrapperContent[] = new cHTMLLabel(i18n('Manual teaser'), 'teaser_manual_' . $this->_id);
 856:         $wrapperContent[] = new cHTMLCheckbox('teaser_manual_' . $this->_id, '', 'teaser_manual_' . $this->_id, ($this->_settings['teaser_manual'] == 'true'));
 857: 
 858:         // $wrapperContent[] = new cHTMLParagraph(i18n('Add article'),
 859:         // 'head_sub');
 860:         $wrapperContent[] = new cHTMLLabel(i18n('Category'), 'teaser_cat_' . $this->_id);
 861:         $wrapperContent[] = buildCategorySelect('teaser_cat_' . $this->_id, 0, 0);
 862:         $wrapperContent[] = new cHTMLLabel(i18n('Article'), 'teaser_art_' . $this->_id);
 863:         $wrapperContent[] = buildArticleSelect('teaser_art_' . $this->_id, 0, 0);
 864: 
 865:         $wrapperContent[] = new cHTMLLabel(i18n('Add'), 'add_art_' . $this->_id);
 866:         $image = new cHTMLImage($this->_cfg['path']['contenido_fullhtml'] . 'images/but_art_new.gif');
 867:         $image->setAttribute('id', 'add_art_' . $this->_id);
 868:         $image->appendStyleDefinition('cursor', 'pointer');
 869:         $wrapperContent[] = $image;
 870: 
 871:         $wrapperContent[] = new cHTMLParagraph(i18n('Included articles'), 'head_sub');
 872:         $selectElement = new cHTMLSelectElement('teaser_manual_art_' . $this->_id, '', 'teaser_manual_art_' . $this->_id, false, '', '', 'manual');
 873:         $selectElement->setAttribute('size', '4');
 874:         $selectElement->setAttribute('multiple', 'multiple');
 875:         // there can be one or multiple selected articles
 876:         if (is_array($this->_settings['teaser_manual_art'])) {
 877:             foreach ($this->_settings['teaser_manual_art'] as $index => $idArt) {
 878:                 $option = new cHTMLOptionElement($this->_getArtName($idArt), $idArt, true);
 879:                 $selectElement->addOptionElement($index, $option);
 880:             }
 881:         } else {
 882:             // check if the article really exists
 883:             $artName = $this->_getArtName($this->_settings['teaser_manual_art']);
 884:             if ($artName != i18n('Unknown article')) {
 885:                 $option = new cHTMLOptionElement($artName, $this->_settings['teaser_manual_art'], true);
 886:                 $selectElement->addOptionElement(0, $option);
 887:             }
 888:         }
 889:         $wrapperContent[] = $selectElement;
 890: 
 891:         $wrapperContent[] = new cHTMLLabel(i18n("Delete"), 'del_art_' . $this->_id);
 892:         $image = new cHTMLImage($this->_cfg['path']['contenido_fullhtml'] . 'images/delete.gif');
 893:         $image->setAttribute('id', 'del_art_' . $this->_id);
 894:         $image->appendStyleDefinition('cursor', 'pointer');
 895:         $wrapperContent[] = $image;
 896: 
 897:         $wrapper->setContent($wrapperContent);
 898:         return $wrapper->render();
 899:     }
 900: 
 901:     /**
 902:      * Function which generated a select box for setting teaser sort argument.
 903:      *
 904:      * @return string
 905:      *         html string of select box
 906:      */
 907:     private function _generateSortSelect() {
 908:         $htmlSelect = new cHTMLSelectElement('teaser_sort_' . $this->_id, '', 'teaser_sort_' . $this->_id);
 909: 
 910:         // set please chose option element
 911:         $htmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
 912:         $htmlSelect->appendOptionElement($htmlSelectOption);
 913: 
 914:         // set other avariable options manually
 915:         $htmlSelectOption = new cHTMLOptionElement(i18n("Sort sequence"), 'sortsequence', false);
 916:         $htmlSelect->appendOptionElement($htmlSelectOption);
 917: 
 918:         $htmlSelectOption = new cHTMLOptionElement(i18n("Creation date"), 'creationdate', false);
 919:         $htmlSelect->appendOptionElement($htmlSelectOption);
 920: 
 921:         $htmlSelectOption = new cHTMLOptionElement(i18n("Published date"), 'publisheddate', false);
 922:         $htmlSelect->appendOptionElement($htmlSelectOption);
 923: 
 924:         $htmlSelectOption = new cHTMLOptionElement(i18n("Modification date"), 'modificationdate', false);
 925:         $htmlSelect->appendOptionElement($htmlSelectOption);
 926: 
 927:         // set default value
 928:         $htmlSelect->setDefault($this->_settings['teaser_sort']);
 929: 
 930:         return $htmlSelect->render();
 931:     }
 932: 
 933:     /**
 934:      * Function which generated a select box for setting teaser sort order argument.
 935:      *
 936:      * @return string
 937:      *         html string of select box
 938:      */
 939:     private function _generateSortOrderSelect() {
 940:         $htmlSelect = new cHTMLSelectElement('teaser_sort_order_' . $this->_id, '', 'teaser_sort_order_' . $this->_id);
 941: 
 942:         // set please chose option element
 943:         $htmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
 944:         $htmlSelect->appendOptionElement($htmlSelectOption);
 945: 
 946:         // set other avariable options manually
 947:         $htmlSelectOption = new cHTMLOptionElement(i18n("Ascending"), 'asc', false);
 948:         $htmlSelect->appendOptionElement($htmlSelectOption);
 949: 
 950:         $htmlSelectOption = new cHTMLOptionElement(i18n("Descending"), 'desc', false);
 951:         $htmlSelect->appendOptionElement($htmlSelectOption);
 952: 
 953:         // set default value
 954:         $htmlSelect->setDefault($this->_settings['teaser_sort_order']);
 955: 
 956:         return $htmlSelect->render();
 957:     }
 958: 
 959:     /**
 960:      * Function which provides select option for cropping teaser images.
 961:      *
 962:      * @return string
 963:      *         html string of select box
 964:      */
 965:     private function _generateCropSelect() {
 966:         $htmlSelect = new cHTMLSelectElement('teaser_image_crop_' . $this->_id, '', 'teaser_image_crop_' . $this->_id);
 967: 
 968:         // set please chose option element
 969:         $htmlSelectOption = new cHTMLOptionElement(i18n("Please choose"), '', true);
 970:         $htmlSelect->appendOptionElement($htmlSelectOption);
 971: 
 972:         // set other avariable options manually
 973:         $htmlSelectOption = new cHTMLOptionElement(i18n("Scaled"), 'false', false);
 974:         $htmlSelect->appendOptionElement($htmlSelectOption);
 975: 
 976:         $htmlSelectOption = new cHTMLOptionElement(i18n("Cropped"), 'true', false);
 977:         $htmlSelect->appendOptionElement($htmlSelectOption);
 978: 
 979:         // set default value
 980:         $htmlSelect->setDefault($this->_settings['teaser_image_crop']);
 981: 
 982:         return $htmlSelect->render();
 983:     }
 984: 
 985:     /**
 986:      * Generates code for the manual tab in which various settings for the
 987:      * manual teaser can be made.
 988:      *
 989:      * @return string
 990:      *         the code for the manual tab
 991:      */
 992:     private function _generateTabManual() {
 993:         // define a wrapper which contains the whole content of the manual tab
 994:         $wrapper = new cHTMLDiv();
 995:         $wrapperContent = array();
 996: 
 997:         $wrapperContent[] = new cHTMLParagraph(i18n("Content visualisation"), 'head_sub');
 998:         $wrapperContent[] = new cHTMLLabel(i18n("Teaser visualisation"), 'teaser_style');
 999:         $wrapperContent[] = $this->_generateStyleSelect();
1000:         $wrapperContent[] = new cHTMLLabel(i18n("Teaser filter"), 'teaser_filter_' . $this->_id);
1001:         $wrapperContent[] = new cHTMLTextbox('teaser_filter_' . $this->_id, $this->_settings['teaser_filter'], '', '', 'teaser_filter_' . $this->_id);
1002:         $wrapperContent[] = new cHTMLLabel(i18n('Character length'), 'teaser_character_limit_' . $this->_id);
1003:         $wrapperContent[] = new cHTMLTextbox('teaser_character_limit_' . $this->_id, $this->_settings['teaser_character_limit'], '', '', 'teaser_character_limit_' . $this->_id);
1004: 
1005:         $wrapperContent[] = new cHTMLParagraph(i18n("Pictures"), 'head_sub');
1006:         $wrapperContent[] = new cHTMLLabel(i18n('Image width'), 'teaser_image_width_' . $this->_id);
1007:         $wrapperContent[] = new cHTMLTextbox('teaser_image_width_' . $this->_id, $this->_settings['teaser_image_width'], '', '', 'teaser_image_width_' . $this->_id);
1008:         $wrapperContent[] = new cHTMLLabel(i18n('Image height'), 'teaser_image_height_' . $this->_id);
1009:         $wrapperContent[] = new cHTMLTextbox('teaser_image_height_' . $this->_id, $this->_settings['teaser_image_height'], '', '', 'teaser_image_height_' . $this->_id);
1010:         $wrapperContent[] = new cHTMLLabel(i18n('Image scale'), 'teaser_image_crop_' . $this->_id);
1011:         $wrapperContent[] = $this->_generateCropSelect();
1012: 
1013:         $wrapperContent[] = new cHTMLParagraph(i18n("Content types"), 'head_sub');
1014:         $wrapperContent[] = new cHTMLLabel(i18n("Headline source"), 'teaser_source_head_' . $this->_id);
1015:         $wrapperContent[] = $this->_generateTypeSelect('teaser_source_head_' . $this->_id, $this->_settings['teaser_source_head'], $this->_settings['teaser_source_head_count']);
1016:         $wrapperContent[] = new cHTMLLabel(i18n("Text source"), 'teaser_source_text_' . $this->_id);
1017:         $wrapperContent[] = $this->_generateTypeSelect('teaser_source_text_' . $this->_id, $this->_settings['teaser_source_text'], $this->_settings['teaser_source_text_count']);
1018:         $wrapperContent[] = new cHTMLLabel(i18n('Image source'), 'teaser_source_image_' . $this->_id);
1019:         $wrapperContent[] = $this->_generateTypeSelect('teaser_source_image_' . $this->_id, $this->_settings['teaser_source_image'], $this->_settings['teaser_source_image_count']);
1020:         $wrapperContent[] = new cHTMLLabel(i18n('Date source'), 'teaser_source_date_' . $this->_id);
1021:         $wrapperContent[] = $this->_generateTypeSelect('teaser_source_date_' . $this->_id, $this->_settings['teaser_source_date'], $this->_settings['teaser_source_date_count']);
1022: 
1023:         $wrapper->setContent($wrapperContent);
1024:         return $wrapper->render();
1025:     }
1026: 
1027:     /**
1028:      * Function retrives name of an article by its id from database.
1029:      *
1030:      * @param int $idArt
1031:      *         CONTENIDO article id
1032:      * @return string
1033:      *         name of article
1034:      */
1035:     private function _getArtName($idArt) {
1036:         $article = new cApiArticleLanguage();
1037:         $article->loadByArticleAndLanguageId((int) $idArt, $this->_lang);
1038: 
1039:         $title = $article->get('title');
1040:         if ($article->isLoaded() && !empty($title)) {
1041:             return $article->get('title');
1042:         } else {
1043:             return i18n('Unknown article');
1044:         }
1045:     }
1046: 
1047: }
1048: 
CMS CONTENIDO 4.9.8 API documentation generated by ApiGen 2.8.0