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\Service\Manager;
  4: 
  5: // dependencies from `charcoal-core`
  6: use Charcoal\Model\Collection;
  7: use Charcoal\Model\Model;
  8: 
  9: // dependencies from `charcoal-base`
 10: use Charcoal\Object\CategoryInterface;
 11: use Charcoal\Object\CategoryTrait;
 12: 
 13: // Local dependencies
 14: use Charcoal\Cms\EventCategory;
 15: use Charcoal\Cms\Config\CmsConfig;
 16: use Charcoal\Cms\EventInterface;
 17: use Charcoal\Cms\Service\Loader\EventLoader;
 18: 
 19: // Psr-7 dependencies
 20: use DateTime;
 21: use DateTimeInterface;
 22: use Exception;
 23: 
 24: /**
 25:  * Event manager
 26:  */
 27: class EventManager extends AbstractManager
 28: {
 29:     use CategoryTrait;
 30: 
 31:     /** @var EventInterface $currentEvent The current event. */
 32:     private $currentEvent;
 33: 
 34:     /** @var integer $currentPage The current Page. */
 35:     private $currentPage;
 36: 
 37:     /** @var integer $numPerPage Events by page. */
 38:     private $numPerPage = 0;
 39: 
 40:     /** @var integer $numPage How many pages. */
 41:     private $numPage;
 42: 
 43:     /** @var boolean $entryCycle Does the pager can cycle indefinitely. */
 44:     private $entryCycle = false;
 45: 
 46:     /** @var EventInterface $nextEvent */
 47:     private $nextEvent;
 48: 
 49:     /** @var EventInterface $prevEvent */
 50:     private $prevEvent;
 51: 
 52:     /** @var integer $page The page number. */
 53:     private $page = 0;
 54: 
 55:     /** @var integer $category Id for category. */
 56:     private $category = 0;
 57: 
 58:     /** @var EventInterface[] $all All the events. */
 59:     private $all = [];
 60: 
 61:     /** @var EventInterface[] $entries The event collection. */
 62:     private $entries = [];
 63: 
 64:     /** @var EventInterface[] $archive The archive events collection. */
 65:     private $archive = [];
 66: 
 67:     /** @var EventInterface $entry An event. */
 68:     private $entry;
 69: 
 70:     /** @var object $objType The event object model. */
 71:     private $objType;
 72: 
 73:     /** @var string $featIdent The config ident for featured events. */
 74:     private $featIdent;
 75: 
 76:     /** @var EventInterface[] $featList The config ident for featured events. */
 77:     private $featList = [];
 78: 
 79:     /** @var EventLoader $loader The event loader provider. */
 80:     private $loader;
 81: 
 82:     /** @var array $mapEvents The events mapped per [year][month][date]. */
 83:     private $mapEvents = [];
 84: 
 85:     /** @var datetime $date Datetime filter */
 86:     private $date;
 87: 
 88:     /** @var mixed $year Year filter. */
 89:     private $year;
 90: 
 91:     /** @var mixed $month Month filter. */
 92:     private $month;
 93: 
 94:     /** @var mixed $day Day filter. */
 95:     private $day;
 96: 
 97:     /**
 98:      * EventManager constructor.
 99:      * @param array $data The Data.
100:      * @throws Exception When $data index is not set.
101:      */
102:     public function __construct(array $data)
103:     {
104:         parent::__construct($data);
105: 
106:         if (!isset($data['event/loader'])) {
107:             throw new Exception('Event Loader must be defined in the EventManager constructor.');
108:         }
109: 
110:         $this->setLoader($data['event/loader']);
111: 
112:         /** @var CmsConfig $eventConfig */
113:         $eventConfig = $this->adminConfig()->eventConfig();
114: 
115:         // City.json
116:         $this->setNumPerPage($eventConfig->get('numPerPage'));
117:         $this->setEntryCycle($eventConfig->get('entryCycle'));
118:         $this->setObjType($eventConfig->get('objType'));
119:         $this->setCategoryItemType($eventConfig->get('category'));
120:         $this->setFeatIdent($eventConfig->get('configFeatIdent'));
121:     }
122: 
123:     /**
124:      * To be displayed events list.
125:      * @return mixed The event collection.
126:      */
127:     public function entries()
128:     {
129:         // Used loader
130:         $loader = $this->loader()->upcoming();
131: 
132:         // Pagination
133:         $page = $this->page();
134: 
135:         // Filters
136:         $cat = $this->category();
137:         $date = $this->date();
138:         $year = $this->year();
139:         $month = $this->month();
140:         $day = $this->day();
141: 
142:         // Basicly.
143:         if ($year && $month && $day && !$date) {
144:             $date = new DateTime($year.'-'.$month.'-'.$day);
145:         }
146: 
147:         // Category is still valid.
148:         $extraSql = '';
149:         if ($cat) {
150:             $extraSql = '
151:             AND
152:                 \''.$cat.'\' IN (category)';
153:         }
154: 
155:         // Get event from specific date.
156:         if ($date) {
157:             $loader = $this->loader()->all();
158:             $proto = $this->loader()->proto();
159:             $table = $proto->source()->table();
160:             $q = 'SELECT * FROM '.$table.'
161:                 WHERE
162:                     \''.$date->format('Y-m-d').'\'
163:                 BETWEEN
164:                     DATE(start_date) AND DATE(end_date)
165:                 AND
166:                     active = 1'.$extraSql;
167: 
168:             $collection = $loader->loadFromQuery($q);
169: 
170:             return $collection;
171:         }
172: 
173:         // YEAR only filter.
174:         if ($year && !$month) {
175:             $loader = $this->loader()->all();
176:             $proto = $this->loader()->proto();
177:             $table = $proto->source()->table();
178:             $q = 'SELECT * FROM '.$table.'
179:                 WHERE
180:                     \''.$this->year().'\' = YEAR(start_date)
181:                 OR
182:                     \''.$this->year().'\' = YEAR(end_date)
183:                 AND
184:                     active = 1'.$extraSql;
185: 
186:             $collection = $loader->loadFromQuery($q);
187: 
188:             return $collection;
189:         }
190: 
191:         // Year AND month filter.
192:         if ($year && $month) {
193:             $between = new DateTime($year.'-'.$month.'-01');
194:             $loader = $this->loader()->all();
195:             $proto = $this->loader()->proto();
196:             $table = $proto->source()->table();
197:             $q = 'SELECT * FROM '.$table.'
198:                 WHERE
199:                     \''.$between->format('Y-m-d H:i:s').'\'
200:                 BETWEEN
201:                     CAST(CONCAT(YEAR(start_date), \'-\', MONTH(start_date), \'-\', 01) AS DATETIME)
202:                 AND
203:                     CAST(CONCAT(YEAR(end_date), \'-\', MONTH(end_date), \'-\', 01) AS DATETIME)
204:                 AND
205:                     active = 1'.$extraSql;
206: 
207:             $collection = $loader->loadFromQuery($q);
208: 
209:             return $collection;
210:         }
211: 
212:         if (isset($this->entries[$cat])) {
213:             if (isset($this->entries[$cat][$page])) {
214:                 return $this->entries[$cat][$page];
215:             }
216:         }
217: 
218:         if ($this->category()) {
219:             $loader->addFilter('category', $this->category(), [ 'operator' => 'in' ]);
220:         }
221: 
222:         if ($this->numPerPage()) {
223:             $loader->setPage($page);
224:             $loader->setNumPerPage($this->numPerPage());
225:         }
226:         $this->entries[$cat][$page] = $loader->load();
227: 
228:         return $this->entries[$cat][$page];
229:     }
230: 
231:     /**
232:      * @param integer|null $id The event id.
233:      * @return mixed
234:      */
235:     public function entry($id = null)
236:     {
237:         if (!$id) {
238:             return $this->currentEvent();
239:         }
240: 
241:         if (!isset($this->entry[$id])) {
242:             /** @var Model $model */
243:             $model = $this->modelFactory();
244:             /** @var EventInterface $entry */
245:             $entry = $model->get($this->objType())->loadfrom('id', $id);
246:             $this->entry[$id] = $entry->id() ? $entry : $this->currentEvent();
247:         }
248: 
249:         return $this->entry[$id];
250:     }
251: 
252:     /**
253:      * All available events
254:      * @return EventInterface[]|Collection The events collection
255:      */
256:     public function all()
257:     {
258:         if ($this->all) {
259:             return $this->all;
260:         }
261: 
262:         $this->all = $this->loader()->all()
263:             ->addOrder('start_date', 'asc')->load();
264: 
265:         return $this->all;
266:     }
267: 
268:     /**
269:      * @return CategoryInterface[]|Collection The category collection.
270:      */
271:     public function loadCategoryItems()
272:     {
273:         /** @var Model $model */
274:         $model = $this->modelFactory();
275:         $proto = $model->get($this->categoryItemType());
276:         $loader = $this->collectionLoader()->setModel($proto);
277:         $loader->addFilter('active', true);
278: 
279:         return $loader->load();
280:     }
281: 
282:     /**
283:      * @param integer $id The category id.
284:      * @return CategoryInterface|EventCategory
285:      */
286:     public function categoryItem($id)
287:     {
288:         $category = $this->modelFactory()->get($this->categoryItemType());
289: 
290:         return $category->load($id);
291:     }
292: 
293:     /**
294:      * Get featured events from config objects with custom filters as options.
295:      * @return mixed
296:      * @param array $options The options for the collection loader.
297:      * @throws Exception When featured news ident is not valid.
298:      */
299:     public function featList(array $options = [])
300:     {
301:         if ($this->featList) {
302:             return $this->featList;
303:         }
304: 
305:         $loader = $this->loader()->published();
306:         $ident = $this->featIdent();
307:         $config = $this->adminConfig();
308: 
309:         if (!$ident || !method_exists($config, $ident)) {
310:             throw new Exception(sprintf(
311:                 'The featured news ident "%s" doesn\'t exist the class "%s"',
312:                 $ident,
313:                 get_class($config)
314:             ));
315:         }
316:         $ids = $config->{$ident}();
317: 
318:         if (!$ids) {
319:             return null;
320:         }
321: 
322:         $ids = explode(',', $ids);
323: 
324:         $loader->addFilter('id', $ids, [ 'operator' => 'in' ])
325:             ->addOrder('id', 'values', [ 'values' => $ids ]);
326: 
327:         if (count($options) > 0) {
328:             foreach ($options as $key => $option) {
329:                 switch ($key) {
330:                     case 'filters':
331:                         $filters = $option;
332:                         foreach ($filters as $f) {
333:                             $filter[] = $f['property'] ?: '';
334:                             $filter[] = $f['val'] ?: '';
335:                             $filter[] = $f['options'] ?: '';
336:                             $filter = join(',', $filter);
337: 
338:                             $loader->addFilter($filter);
339:                         }
340:                         break;
341:                     case 'page':
342:                         $loader->setPage($option);
343:                         break;
344:                     case 'numPerPage':
345:                         $loader->setNumPerPage($option);
346:                         break;
347:                 }
348:             }
349:         }
350: 
351:         $this->featList = $loader->load();
352: 
353:         return $this->featList;
354:     }
355: 
356:     /**
357:      * @return EventInterface[]|Collection
358:      */
359:     public function archive()
360:     {
361:         $page = $this->page();
362:         $cat = $this->category();
363:         if (isset($this->archive[$cat])) {
364:             if (isset($this->archive[$cat][$page])) {
365:                 return $this->archive[$cat][$page];
366:             }
367:         }
368: 
369:         $loader = $this->loader()->archive();
370: 
371:         if ($this->category()) {
372:             $loader->addFilter('category', $this->category(), [ 'operator' => 'in' ]);
373:         }
374:         if ($this->numPerPage()) {
375:             $loader->setPage($this->page());
376:             $loader->setNumPerPage($this->numPerPage());
377:         }
378: 
379:         $this->archive[$cat][$page] = $loader->load();
380: 
381:         return $this->archive[$cat][$page];
382:     }
383: 
384:     /**
385:      * Get the latest event.
386:      * @return EventInterface|array The latest event.
387:      */
388:     public function latest()
389:     {
390:         $entries = $this->entries();
391: 
392:         if (isset($entries[0])) {
393:             return $entries[0];
394:         } else {
395:             // NO EVENT!
396:             return [];
397:         }
398:     }
399: 
400:     /**
401:      * @return mixed The previous event
402:      */
403:     public function prev()
404:     {
405:         if ($this->prevEvent) {
406:             return $this->prevEvent;
407:         } else {
408:             return $this->setPrevNext()->prevEvent;
409:         }
410:     }
411: 
412:     /**
413:      * @return mixed The next event
414:      */
415:     public function next()
416:     {
417:         if ($this->nextEvent) {
418:             return $this->nextEvent;
419:         } else {
420:             return $this->setPrevNext()->nextEvent;
421:         }
422:     }
423: 
424:     /**
425:      * @return float|int The current event index page ident.
426:      */
427:     public function currentPage()
428:     {
429:         if ($this->currentPage) {
430:             return $this->currentPage;
431:         }
432:         if (!$this->currentEvent() || !$this->currentEvent()['id']) {
433:             $this->currentPage = 1;
434: 
435:             return 1;
436:         }
437:         $all = $this->all();
438:         $i = 0;
439:         foreach ($all as $event) {
440:             $i++;
441:             if ($event->id() == $this->currentEvent()['id']) {
442:                 break;
443:             }
444:         }
445: 
446:         $this->currentPage = $this->numPerPage() ? ceil($i / $this->numPerPage()) : 1;
447: 
448:         return $this->currentPage;
449:     }
450: 
451:     /**
452:      * @param mixed $date The date from which to load.
453:      * @return array
454:      */
455:     public function getEventsByDate($date)
456:     {
457:         if (!($date instanceof DateTimeInterface)) {
458:             $date = new DateTime($date);
459:         }
460: 
461:         $map = $this->mapEvents();
462:         $year = $date->format('Y');
463:         $month = $date->format('m');
464:         $day = $date->format('d');
465: 
466:         if (isset($map[$year][$month][$day])) {
467:             return $map[$year][$month][$day];
468:         }
469: 
470:         return [];
471:     }
472: 
473:     // ==========================================================================
474:     // GETTERS
475:     // ==========================================================================
476: 
477:     /**
478:      * @return mixed
479:      */
480:     public function currentEvent()
481:     {
482:         if (!$this->currentEvent) {
483:             $this->currentEvent = $this->latest();
484:         }
485: 
486:         return $this->currentEvent;
487:     }
488: 
489:     /**
490:      * @return integer
491:      */
492:     public function numPerPage()
493:     {
494:         return $this->numPerPage;
495:     }
496: 
497:     /**
498:      * @return boolean
499:      */
500:     public function entryCycle()
501:     {
502:         return $this->entryCycle;
503:     }
504: 
505:     /**
506:      * Amount of event (total)
507:      * @return integer How many event?
508:      */
509:     public function numEvent()
510:     {
511:         return !!(count($this->entries()));
512:     }
513: 
514:     /**
515:      * The total amount of pages.
516:      * @return float
517:      */
518:     public function numPages()
519:     {
520:         if ($this->numPage) {
521:             $this->numPage;
522:         };
523: 
524:         $entries = $this->entries();
525:         $count = count($entries);
526: 
527:         if ($this->numPerPage()) {
528:             $this->numPage = ceil($count / $this->numPerPage());
529:         } else {
530:             $this->numPage = 1;
531:         }
532: 
533:         return $this->numPage;
534:     }
535: 
536:     /**
537:      * Is there a pager.
538:      * @return boolean
539:      */
540:     public function hasPager()
541:     {
542:         return ($this->numPages() > 1);
543:     }
544: 
545:     /**
546:      * @return integer
547:      */
548:     public function page()
549:     {
550:         return $this->page;
551:     }
552: 
553:     /**
554:      * @return integer
555:      */
556:     public function category()
557:     {
558:         return $this->category;
559:     }
560: 
561:     /**
562:      * @return mixed
563:      */
564:     public function objType()
565:     {
566:         return $this->objType;
567:     }
568: 
569:     /**
570:      * @return mixed
571:      */
572:     public function featIdent()
573:     {
574:         return $this->featIdent;
575:     }
576: 
577:     /**
578:      * @return EventLoader
579:      */
580:     public function loader()
581:     {
582:         return $this->loader;
583:     }
584: 
585:     /**
586:      * Datetime object OR null.
587:      * @return mixed Datetime or null.
588:      */
589:     public function date()
590:     {
591:         return $this->date;
592:     }
593: 
594:     /**
595:      * Full year
596:      * @return integer Full year.
597:      */
598:     public function year()
599:     {
600:         return $this->year;
601:     }
602: 
603:     /**
604:      * Month
605:      * @return mixed month.
606:      */
607:     public function month()
608:     {
609:         return $this->month;
610:     }
611: 
612:     /**
613:      * Day
614:      * @return mixed day.
615:      */
616:     public function day()
617:     {
618:         return $this->day;
619:     }
620: 
621:     // ==========================================================================
622:     // SETTERS
623:     // ==========================================================================
624: 
625:     /**
626:      * @param mixed $currentEvent The current event context.
627:      * @return self
628:      */
629:     public function setCurrentEvent($currentEvent)
630:     {
631:         $this->currentEvent = $currentEvent;
632: 
633:         return $this;
634:     }
635: 
636:     /**
637:      * @param integer $numPerPage The number of event per page.
638:      * @return self
639:      */
640:     public function setNumPerPage($numPerPage)
641:     {
642:         $this->numPerPage = $numPerPage;
643: 
644:         return $this;
645:     }
646: 
647:     /**
648:      * @param boolean $entryCycle Next and Prev cycles indefinitely.
649:      * @return self
650:      */
651:     public function setEntryCycle($entryCycle)
652:     {
653:         $this->entryCycle = $entryCycle;
654: 
655:         return $this;
656:     }
657: 
658:     /**
659:      * @param integer $page The page number to load.
660:      * @return self
661:      */
662:     public function setPage($page)
663:     {
664:         $this->page = $page;
665: 
666:         return $this;
667:     }
668: 
669:     /**
670:      * @param integer $category The current entry category.
671:      * @return self
672:      */
673:     public function setCategory($category)
674:     {
675:         $this->category = $category;
676: 
677:         return $this;
678:     }
679: 
680:     /**
681:      * @param mixed $objType The object type.
682:      * @return self
683:      */
684:     public function setObjType($objType)
685:     {
686:         $this->objType = $objType;
687: 
688:         return $this;
689:     }
690: 
691:     /**
692:      * @param mixed $featIdent The featured list ident.
693:      * @return self
694:      */
695:     public function setFeatIdent($featIdent)
696:     {
697:         $this->featIdent = $featIdent;
698: 
699:         return $this;
700:     }
701: 
702:     /**
703:      * @param EventLoader|null $loader The event loader provider.
704:      * @return self
705:      */
706:     public function setLoader($loader)
707:     {
708:         $this->loader = $loader;
709: 
710:         return $this;
711:     }
712: 
713:     /**
714:      * Set date filter.
715:      * @param DateTime $date Date filter.
716:      * @return self
717:      */
718:     public function setDate(DateTime $date)
719:     {
720:         $this->date = $date;
721: 
722:         return $this;
723:     }
724: 
725:     /**
726:      * Full year.
727:      * @param mixed $year Full year.
728:      * @throws Exception If argument is not scalar.
729:      * @return EventManager
730:      */
731:     public function setYear($year)
732:     {
733:         if (!is_scalar($year)) {
734:             throw new Exception('Year must be a string or an integer in EventManager setYear method.');
735:         }
736:         $this->year = $year;
737: 
738:         return $this->year;
739:     }
740: 
741:     /**
742:      * Month.
743:      * @param mixed $month Specific month.
744:      * @throws Exception If argument is not scalar.
745:      * @return EventManager
746:      */
747:     public function setMonth($month)
748:     {
749:         if (!is_scalar($month)) {
750:             throw new Exception('Month must be a string or an integer in EventManager setMonth method.');
751:         }
752:         $this->month = $month;
753: 
754:         return $this;
755:     }
756: 
757:     /**
758:      * Day.
759:      * @param mixed $day Specific day.
760:      * @throws Exception If argument is not scalar.
761:      * @return EventManager
762:      */
763:     public function setDay($day)
764:     {
765:         if (!is_scalar($day)) {
766:             throw new Exception('Day must be a string or an integer in EventManager setDay method.');
767:         }
768:         $this->day = $day;
769: 
770:         return $this;
771:     }
772: 
773:     // ==========================================================================
774:     // UTILS
775:     // ==========================================================================
776: 
777:     /**
778:      * Set the Prev and Next event
779:      * @return $this
780:      */
781:     public function setPrevNext()
782:     {
783:         if ($this->prevEvent && $this->nextEvent) {
784:             return $this;
785:         }
786:         $entries = $this->entries();
787: 
788:         $isPrev = false;
789:         $isNext = false;
790:         $firstEvent = false;
791:         $lastEvent = false;
792: 
793:         foreach ($entries as $event) {
794:             // Obtain th first event.
795:             if (!$firstEvent) {
796:                 $firstEvent = $event;
797:             }
798:             $lastEvent = $event;
799:             // Find the current event
800:             if ($event->id() == $this->currentEvent()['id']) {
801:                 $isNext = true;
802:                 $isPrev = true;
803: 
804:                 continue;
805:             }
806:             if (!$isPrev) {
807:                 $this->prevEvent = $event;
808:             }
809:             // Store the next event
810:             if ($isNext) {
811:                 $this->nextEvent = $event;
812: 
813:                 $isNext = false;
814:             }
815:         }
816: 
817:         if ($this->entryCycle()) {
818:             if (!$this->nextEvent) {
819:                 $this->nextEvent = $firstEvent;
820:             }
821: 
822:             if (!$this->prevEvent) {
823:                 $this->prevEvent = $lastEvent;
824:             }
825:         }
826: 
827:         return $this;
828:     }
829: 
830:     /**
831:      * Mapping between events and dates
832:      * @return array The array containing events stored as [$year][$month][$day][event]
833:      */
834:     public function mapEvents()
835:     {
836:         if ($this->mapEvents) {
837:             return $this->mapEvents;
838:         }
839: 
840:         $events = $this->all();
841: 
842:         $out = [];
843:         foreach ($events as $ev) {
844:             $firstDate = $ev->startDate();
845:             $lastDate = $ev->endDate();
846: 
847:             $current = new DateTime();
848:             $current->setTimestamp($firstDate->getTimestamp());
849: 
850:             while ($current <= $lastDate) {
851:                 $year = $current->format('Y');
852:                 $month = $current->format('m');
853:                 $day = $current->format('d');
854: 
855:                 if (!isset($out[$year])) {
856:                     $out[$year] = [];
857:                 }
858: 
859:                 if (!isset($out[$year][$month])) {
860:                     $out[$year][$month] = [];
861:                 }
862: 
863:                 if (!isset($out[$year][$month][$day])) {
864:                     $out[$year][$month][$day] = [];
865:                 }
866: 
867:                 $out[$year][$month][$day][] = $ev;
868: 
869:                 $current->modify('+1 day');
870:             }
871:         }
872: 
873:         $this->mapEvents = $out;
874: 
875:         return $this->mapEvents;
876:     }
877: }
878: 
API documentation generated by ApiGen