Overview

Namespaces

  • Charcoal
    • Admin
      • Widget
        • Cms
    • Cms
      • Config
      • Mixin
        • Traits
      • Route
      • Section
      • Service
        • Loader
        • Manager
      • ServiceProvider
      • Support
        • Helpers
        • Interfaces
        • Traits
    • Property

Classes

  • Charcoal\Admin\Widget\Cms\HierarchicalSectionTableWidget
  • Charcoal\Admin\Widget\Cms\SectionTableWidget
  • Charcoal\Cms\AbstractDocument
  • Charcoal\Cms\AbstractEvent
  • Charcoal\Cms\AbstractFaq
  • Charcoal\Cms\AbstractImage
  • Charcoal\Cms\AbstractNews
  • Charcoal\Cms\AbstractSection
  • Charcoal\Cms\AbstractText
  • Charcoal\Cms\AbstractVideo
  • Charcoal\Cms\Config
  • Charcoal\Cms\Config\CmsConfig
  • Charcoal\Cms\Config\EventConfig
  • Charcoal\Cms\Config\NewsConfig
  • Charcoal\Cms\Config\SectionConfig
  • Charcoal\Cms\Document
  • Charcoal\Cms\DocumentCategory
  • Charcoal\Cms\EmptySection
  • Charcoal\Cms\Event
  • Charcoal\Cms\EventCategory
  • Charcoal\Cms\ExternalSection
  • Charcoal\Cms\Faq
  • Charcoal\Cms\FaqCategory
  • Charcoal\Cms\Image
  • Charcoal\Cms\ImageCategory
  • Charcoal\Cms\News
  • Charcoal\Cms\NewsCategory
  • Charcoal\Cms\Route\EventRoute
  • Charcoal\Cms\Route\GenericRoute
  • Charcoal\Cms\Route\NewsRoute
  • Charcoal\Cms\Route\SectionRoute
  • Charcoal\Cms\Section
  • Charcoal\Cms\Section\BlocksSection
  • Charcoal\Cms\Section\ContentSection
  • Charcoal\Cms\Service\Loader\AbstractLoader
  • Charcoal\Cms\Service\Loader\EventLoader
  • Charcoal\Cms\Service\Loader\NewsLoader
  • Charcoal\Cms\Service\Loader\SectionLoader
  • Charcoal\Cms\Service\Manager\AbstractManager
  • Charcoal\Cms\Service\Manager\EventManager
  • Charcoal\Cms\Service\Manager\NewsManager
  • Charcoal\Cms\ServiceProvider\CmsServiceProvider
  • Charcoal\Cms\Support\Helpers\DateHelper
  • Charcoal\Cms\Tag
  • Charcoal\Cms\Text
  • Charcoal\Cms\TextCategory
  • Charcoal\Cms\Video
  • Charcoal\Cms\VideoCategory
  • Charcoal\Property\TemplateOptionsProperty
  • Charcoal\Property\TemplateProperty

Interfaces

  • Charcoal\Cms\DocumentInterface
  • Charcoal\Cms\EventInterface
  • Charcoal\Cms\FaqInterface
  • Charcoal\Cms\ImageInterface
  • Charcoal\Cms\MetatagInterface
  • Charcoal\Cms\Mixin\HasContentBlocksInterface
  • Charcoal\Cms\NewsInterface
  • Charcoal\Cms\SearchableInterface
  • Charcoal\Cms\SectionInterface
  • Charcoal\Cms\Support\Interfaces\EventManagerAwareInterface
  • Charcoal\Cms\Support\Interfaces\NewsManagerAwareInterface
  • Charcoal\Cms\Support\Interfaces\SectionLoaderAwareInterface
  • Charcoal\Cms\TemplateableInterface
  • Charcoal\Cms\TextInterface
  • Charcoal\Cms\VideoInterface

Traits

  • Charcoal\Admin\Widget\Cms\SectionTableTrait
  • Charcoal\Cms\MetatagTrait
  • Charcoal\Cms\Mixin\Traits\HasContentBlocksTrait
  • Charcoal\Cms\SearchableTrait
  • Charcoal\Cms\Support\Traits\DateHelperAwareTrait
  • Charcoal\Cms\Support\Traits\EventManagerAwareTrait
  • Charcoal\Cms\Support\Traits\NewsManagerAwareTrait
  • Charcoal\Cms\Support\Traits\SectionLoaderAwareTrait
  • Charcoal\Cms\TemplateableTrait
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: namespace Charcoal\Cms;
  4: 
  5: use DateTime;
  6: use DateTimeInterface;
  7: use InvalidArgumentException;
  8: 
  9: // From PSR-7
 10: use Psr\Http\Message\RequestInterface;
 11: use Psr\Http\Message\ResponseInterface;
 12: 
 13: // From 'charcoal-object'
 14: use Charcoal\Object\Content;
 15: use Charcoal\Object\CategorizableInterface;
 16: use Charcoal\Object\CategorizableTrait;
 17: use Charcoal\Object\PublishableInterface;
 18: use Charcoal\Object\PublishableTrait;
 19: use Charcoal\Object\RoutableInterface;
 20: use Charcoal\Object\RoutableTrait;
 21: 
 22: // From 'charcoal-translator'
 23: use Charcoal\Translator\Translation;
 24: 
 25: // From 'charcoal-cms'
 26: use Charcoal\Cms\MetatagInterface;
 27: use Charcoal\Cms\NewsInterface;
 28: use Charcoal\Cms\SearchableInterface;
 29: use Charcoal\Cms\SearchableTrait;
 30: use Charcoal\Cms\TemplateableInterface;
 31: 
 32: // Local dependencies
 33: use Charcoal\Cms\Support\Helpers\DateHelper;
 34: 
 35: // Pimple dependencies
 36: use Pimple\Container;
 37: 
 38: /**
 39:  * News
 40:  */
 41: abstract class AbstractNews extends Content implements
 42:     CategorizableInterface,
 43:     MetatagInterface,
 44:     NewsInterface,
 45:     PublishableInterface,
 46:     RoutableInterface,
 47:     SearchableInterface,
 48:     TemplateableInterface
 49: {
 50:     use CategorizableTrait;
 51:     use PublishableTrait;
 52:     use MetatagTrait;
 53:     use RoutableTrait;
 54:     use SearchableTrait;
 55:     use TemplateableTrait;
 56: 
 57:     /**
 58:      * @var Translation|string|null
 59:      */
 60:     private $title;
 61: 
 62:     /**
 63:      * @var Translation|string|null
 64:      */
 65:     private $subtitle;
 66: 
 67:     /**
 68:      * @var Translation|string|null
 69:      */
 70:     private $summary;
 71: 
 72:     /**
 73:      * @var Translation|string|null
 74:      */
 75:     private $content;
 76: 
 77:     /**
 78:      * @var Translation|string|null
 79:      */
 80:     private $image;
 81: 
 82:     /**
 83:      * @var DateTimeInterface|null
 84:      */
 85:     private $newsDate;
 86: 
 87:     /**
 88:      * @var Translation|string|null
 89:      */
 90:     private $infoUrl;
 91: 
 92:     /**
 93:      * @var array
 94:      */
 95:     protected $keywords;
 96: 
 97:     // ==========================================================================
 98:     // INIT
 99:     // ==========================================================================
100: 
101:     /**
102:      * Section constructor.
103:      * @param array $data The data.
104:      */
105:     public function __construct(array $data = null)
106:     {
107:         parent::__construct($data);
108: 
109:         if (is_callable([ $this, 'defaultData' ])) {
110:             $this->setData($this->defaultData());
111:         }
112:     }
113: 
114:     // ==========================================================================
115:     // FUNCTIONS
116:     // ==========================================================================
117: 
118:     /**
119:      * In the datetime attribute of the <time> tag
120:      * @return string The datetime attribute formatted.
121:      */
122:     public function dateTimeDate()
123:     {
124:         $newsDate = $this->newsDate();
125: 
126:         return $newsDate->format('Y-m-d H:i:s');
127:     }
128: 
129:     /**
130:      * Some dates cannot be null
131:      * @return void
132:      */
133:     public function verifyDates()
134:     {
135:         if (!$this->newsDate()) {
136:             $this->setNewsDate('now');
137:         }
138: 
139:         if (!$this->publishDate()) {
140:             $this->setPublishDate('now');
141:         }
142:     }
143: 
144:     /**
145:      * @return string The date filtered for admin dual select input and others.
146:      */
147:     public function adminDateFilter()
148:     {
149:         return $this->newsDate()->format('Y-m-d');
150:     }
151: 
152:     // ==========================================================================
153:     // SETTERS
154:     // ==========================================================================
155: 
156:     /**
157:      * @param mixed $title The news title (localized).
158:      * @return self
159:      */
160:     public function setTitle($title)
161:     {
162:         $this->title = $this->translator()->translation($title);
163: 
164:         return $this;
165:     }
166: 
167:     /**
168:      * @param  mixed $subtitle The news subtitle (localized).
169:      * @return self
170:      */
171:     public function setSubtitle($subtitle)
172:     {
173:         $this->subtitle = $this->translator()->translation($subtitle);
174: 
175:         return $this;
176:     }
177: 
178:     /**
179:      * @param mixed $summary The news summary (localized).
180:      * @return self
181:      */
182:     public function setSummary($summary)
183:     {
184:         $this->summary = $this->translator()->translation($summary);
185: 
186:         return $this;
187:     }
188: 
189:     /**
190:      * @param mixed $content The news content (localized).
191:      * @return self
192:      */
193:     public function setContent($content)
194:     {
195:         $this->content = $this->translator()->translation($content);
196: 
197:         return $this;
198:     }
199: 
200:     /**
201:      * @param mixed $image The section main image (localized).
202:      * @return self
203:      */
204:     public function setImage($image)
205:     {
206:         $this->image = $this->translator()->translation($image);
207: 
208:         return $this;
209:     }
210: 
211:     /**
212:      * @param mixed $url The info URL (news source or where to find more information; localized).
213:      * @return self
214:      */
215:     public function setInfoUrl($url)
216:     {
217:         $this->infoUrl = $this->translator()->translation($url);
218: 
219:         return $this;
220:     }
221: 
222:     /**
223:      * @param  string|DateTimeInterface $newsDate The news date.
224:      * @throws InvalidArgumentException If the timestamp is invalid.
225:      * @return self
226:      */
227:     public function setNewsDate($newsDate)
228:     {
229:         if ($newsDate === null || $newsDate === '') {
230:             $this->newsDate = null;
231: 
232:             return $this;
233:         }
234:         if (is_string($newsDate)) {
235:             $newsDate = new DateTime($newsDate);
236:         }
237:         if (!($newsDate instanceof DateTimeInterface)) {
238:             throw new InvalidArgumentException(
239:                 'Invalid "Revision Date" value. Must be a date/time string or a DateTimeInterface object.'
240:             );
241:         }
242:         $this->newsDate = $newsDate;
243: 
244:         return $this;
245:     }
246: 
247:     /**
248:      * Set the object's keywords.
249:      *
250:      * @param  string|string[] $keywords One or more entries.
251:      * @return self
252:      */
253:     public function setKeywords($keywords)
254:     {
255:         $this->keywords = $this->parseAsMultiple($keywords);
256: 
257:         return $this;
258:     }
259: 
260:     // ==========================================================================
261:     // GETTERS
262:     // ==========================================================================
263: 
264:     /**
265:      * @return Translation|string|null
266:      */
267:     public function title()
268:     {
269:         return $this->title;
270:     }
271: 
272:     /**
273:      * @return Translation|string|null
274:      */
275:     public function subtitle()
276:     {
277:         return $this->subtitle;
278:     }
279: 
280:     /**
281:      * @return Translation|string|null
282:      */
283:     public function summary()
284:     {
285:         return $this->summary;
286:     }
287: 
288:     /**
289:      * @return Translation|string|null
290:      */
291:     public function infoUrl()
292:     {
293:         return $this->infoUrl;
294:     }
295: 
296:     /**
297:      * @return DateTimeInterface|null
298:      */
299:     public function newsDate()
300:     {
301:         return $this->newsDate;
302:     }
303: 
304:     /**
305:      * @return Translation|string|null
306:      */
307:     public function content()
308:     {
309:         return $this->content;
310:     }
311: 
312:     /**
313:      * @return Translation|string|null
314:      */
315:     public function image()
316:     {
317:         return $this->image;
318:     }
319: 
320:     // ==========================================================================
321:     // META TAGS
322:     // ==========================================================================
323: 
324:     /**
325:      * MetatagTrait > canonical_url
326:      *
327:      * @return string
328:      * @todo
329:      */
330:     public function canonicalUrl()
331:     {
332:         return '';
333:     }
334: 
335:     /**
336:      * @return Translation|string|null
337:      */
338:     public function defaultMetaTitle()
339:     {
340:         return $this->title();
341:     }
342: 
343:     /**
344:      * @return Translation|string|null
345:      */
346:     public function defaultMetaDescription()
347:     {
348:         $content = $this->translator()->translation($this->content());
349:         if ($content instanceof Translation) {
350:             $desc = [];
351:             foreach ($content->data() as $lang => $text) {
352:                 $desc[$lang] = strip_tags($text);
353:             }
354: 
355:             return $this->translator()->translation($desc);
356:         }
357: 
358:         return null;
359:     }
360: 
361:     /**
362:      * @return Translation|string|null
363:      */
364:     public function defaultMetaImage()
365:     {
366:         return $this->image();
367:     }
368: 
369:     /**
370:      * Retrieve the object's keywords.
371:      *
372:      * @return string[]
373:      */
374:     public function keywords()
375:     {
376:         return $this->keywords;
377:     }
378: 
379:     // ==========================================================================
380:     // Utils
381:     // ==========================================================================
382: 
383:     /**
384:      * Parse the property value as a "multiple" value type.
385:      *
386:      * @param  mixed                    $value     The value being converted to an array.
387:      * @param  string|PropertyInterface $separator The boundary string.
388:      * @return array
389:      */
390:     public function parseAsMultiple($value, $separator = ',')
391:     {
392:         if (!isset($value) ||
393:             (is_string($value) && !strlen(trim($value))) ||
394:             (is_array($value) && !count(array_filter($value, 'strlen')))
395:         ) {
396:             return [];
397:         }
398: 
399:         /**
400:          * This property is marked as "multiple".
401:          * Manually handling the resolution to array
402:          * until the property itself manages this.
403:          */
404:         if (is_string($value)) {
405:             return explode($separator, $value);
406:         }
407: 
408:         /**
409:          * If the parameter isn't an array yet,
410:          * means we might be dealing with an integer,
411:          * an empty string, or an object.
412:          */
413:         if (!is_array($value)) {
414:             return [ $value ];
415:         }
416: 
417:         return $value;
418:     }
419: 
420:     // ==========================================================================
421:     // EVENTS
422:     // ==========================================================================
423: 
424:     /**
425:      * {@inheritdoc}
426:      *
427:      * @return boolean
428:      */
429:     public function preSave()
430:     {
431:         $this->verifyDates();
432:         $this->setSlug($this->generateSlug());
433:         $this->generateDefaultMetaTags();
434: 
435:         return parent::preSave();
436:     }
437: 
438:     /**
439:      * {@inheritdoc}
440:      *
441:      * @param array $properties Optional properties to update.
442:      * @return boolean
443:      */
444:     public function preUpdate(array $properties = null)
445:     {
446:         $this->verifyDates();
447:         $this->setSlug($this->generateSlug());
448:         $this->generateDefaultMetaTags();
449: 
450:         return parent::preUpdate($properties);
451:     }
452: 
453:     /**
454:      * @return boolean Parent postSave().
455:      */
456:     public function postSave()
457:     {
458:         // RoutableTrait
459:         $this->generateObjectRoute($this->slug());
460: 
461:         return parent::postSave();
462:     }
463: 
464:     /**
465:      * @param array|null $properties Properties.
466:      * @return boolean
467:      */
468:     public function postUpdate(array $properties = null)
469:     {
470:         // RoutableTrait
471:         $this->generateObjectRoute($this->slug());
472: 
473:         return parent::postUpdate($properties);
474:     }
475: 
476:     /**
477:      * GenericRoute checks if the route is active.
478:      * Default in RoutableTrait.
479:      *
480:      * @return boolean
481:      */
482:     public function isActiveRoute()
483:     {
484:         return (
485:             $this->active() &&
486:             $this->isPublished()
487:         );
488:     }
489: }
490: 
API documentation generated by ApiGen