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
  • Smarty
    • Cacher
    • Compiler
    • Config
    • Debug
    • PluginsBlock
    • PluginsFilter
    • PluginsFunction
    • PluginsInternal
    • PluginsModifier
    • PluginsModifierCompiler
    • PluginsShared
    • Security
    • Template
    • TemplateResources
  • Swift
    • ByteStream
    • CharacterStream
    • Encoder
    • Events
    • KeyCache
    • Mailer
    • Mime
    • Plugins
    • Transport

Classes

  • Swift_FailoverTransport
  • Swift_LoadBalancedTransport
  • Swift_MailTransport
  • Swift_Plugins_Loggers_ArrayLogger
  • Swift_Plugins_Loggers_EchoLogger
  • Swift_SendmailTransport
  • Swift_SmtpTransport
  • Swift_Transport_AbstractSmtpTransport
  • Swift_Transport_Esmtp_Auth_CramMd5Authenticator
  • Swift_Transport_Esmtp_Auth_LoginAuthenticator
  • Swift_Transport_Esmtp_Auth_PlainAuthenticator
  • Swift_Transport_Esmtp_AuthHandler
  • Swift_Transport_EsmtpTransport
  • Swift_Transport_FailoverTransport
  • Swift_Transport_LoadBalancedTransport
  • Swift_Transport_MailTransport
  • Swift_Transport_SendmailTransport
  • Swift_Transport_SimpleMailInvoker
  • Swift_Transport_StreamBuffer

Interfaces

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