1: <?php
2:
3: namespace Charcoal\Cms\Service\Manager;
4:
5:
6: use Charcoal\Model\Collection;
7:
8:
9: use Charcoal\Object\CategoryInterface;
10: use Charcoal\Object\CategoryTrait;
11:
12:
13: use Charcoal\Cms\Config\CmsConfig;
14: use Charcoal\Cms\NewsInterface;
15: use Charcoal\Cms\Service\Loader\NewsLoader;
16:
17:
18: use Exception;
19:
20: 21: 22:
23: class NewsManager extends AbstractManager
24: {
25: use CategoryTrait;
26:
27:
28: protected $currentNews;
29:
30:
31: protected $currentPage;
32:
33:
34: protected $numPerPage = 0;
35:
36:
37: protected $numPages;
38:
39:
40: protected $entryCycle = false;
41:
42:
43: protected $nextNews;
44:
45:
46: protected $prevNews;
47:
48:
49: protected $page = 0;
50:
51:
52: protected $category = 0;
53:
54:
55: protected $all = [];
56:
57:
58: protected $entries = [];
59:
60:
61: protected $archive = [];
62:
63:
64: protected $entry;
65:
66:
67: protected $objType;
68:
69:
70: protected $featIdent;
71:
72:
73: protected $featList = [];
74:
75:
76: protected $loader;
77:
78: 79: 80:
81: protected $categoryItem = [];
82:
83: 84: 85: 86: 87:
88: public function __construct(array $data)
89: {
90: parent::__construct($data);
91:
92: if (!isset($data['news/loader'])) {
93: throw new Exception('News Loader must be defined in the NewsManager constructor.');
94: }
95:
96: $this->setLoader($data['news/loader']);
97:
98:
99: $newsConfig = $this->adminConfig()->newsConfig();
100:
101: $this->setNumPerPage($newsConfig->get('numPerPage'));
102: $this->setEntryCycle($newsConfig->get('entryCycle'));
103: $this->setObjType($newsConfig->get('objType'));
104: $this->setCategoryItemType($newsConfig->get('category'));
105: $this->setFeatIdent($newsConfig->get('configFeatIdent'));
106: }
107:
108: 109: 110: 111:
112: public function entries()
113: {
114: $page = $this->page();
115: $cat = $this->category();
116: if (isset($this->entries[$cat])) {
117: if (isset($this->entries[$cat][$page])) {
118: return $this->entries[$cat][$page];
119: }
120: }
121:
122: $loader = $this->entriesLoader();
123:
124: $this->entries[$cat][$page] = $loader->load();
125:
126: return $this->entries[$cat][$page];
127: }
128:
129: 130: 131:
132: public function entriesLoader()
133: {
134: $loader = $this->loader()->upcoming();
135: $loader->addOrder('news_date', 'desc');
136:
137: if ($this->category()) {
138: $loader->addFilter('category', $this->category(), [ 'operator' => 'in' ]);
139: }
140: if ($this->numPerPage()) {
141: $loader->setPage($this->page());
142:
143: $numPerPage = !!($this->page()) ? $this->numPerPage() : 0;
144: $loader->setNumPerPage($numPerPage);
145: }
146:
147: return $loader;
148: }
149:
150: 151: 152: 153:
154: public function entry($id = null)
155: {
156: if (!$id) {
157: return $this->currentNews();
158: }
159:
160: if (!isset($this->entry[$id])) {
161: $entry = $this->modelFactory()->get($this->objType())->loadFrom('id', $id);
162: $this->entry[$id] = $entry->id() ? $entry : $this->currentNews();
163: }
164:
165: return $this->entry[$id];
166: }
167:
168: 169: 170: 171:
172: public function all()
173: {
174: if ($this->all) {
175: return $this->all;
176: }
177:
178: $this->all = $this->loader()->all()->addOrder('news_date', 'desc')->load();
179:
180: return $this->all;
181: }
182:
183: 184: 185:
186: public function loadCategoryItems()
187: {
188: $proto = $this->modelFactory()->create($this->categoryItemType());
189: $loader = $this->collectionLoader()->setModel($proto);
190: $loader->addFilter('active', true);
191:
192: return $loader->load();
193: }
194:
195: 196: 197: 198:
199: public function categoryItem($id)
200: {
201: if (isset($this->categoryItem[$id])) {
202: return $this->categoryItem[$id];
203: }
204: $category = $this->modelFactory()->create($this->categoryItemType());
205:
206: $this->categoryItem[$id] = $category->load($id);
207:
208: return $this->categoryItem[$id];
209: }
210:
211: 212: 213: 214: 215:
216: public function featList(array $options = [])
217: {
218: if ($this->featList) {
219: return $this->featList;
220: }
221:
222: $loader = $this->loader()->published();
223: $ident = $this->featIdent();
224: $config = $this->adminConfig();
225:
226: if (!$ident || !method_exists($config, $ident)) {
227: throw new Exception(sprintf(
228: 'The featured news ident "%s" doesn\'t exist the class "%s"',
229: $ident,
230: get_class($config)
231: ));
232: }
233: $ids = $config->{$ident}();
234:
235: if (!$ids) {
236: return null;
237: }
238:
239: $ids = explode(',', $ids);
240:
241: $loader->addFilter('id', $ids, [ 'operator' => 'in' ])
242: ->addOrder('id', 'values', [ 'values' => $ids ]);
243:
244: if (count($options) > 0) {
245: foreach ($options as $key => $option) {
246: switch ($key) {
247: case 'filters':
248: $filters = $option;
249: foreach ($filters as $f) {
250: $filter[] = $f['property'] ?: '';
251: $filter[] = $f['val'] ?: '';
252: $filter[] = $f['options'] ?: '';
253: $filter = join(',', $filter);
254:
255: $loader->addFilter($filter);
256: }
257: break;
258: case 'page':
259: $loader->setPage($option);
260: break;
261: case 'numPerPage':
262: $loader->setNumPerPage($option);
263: break;
264: }
265: }
266: }
267:
268: $this->featList = $loader->load();
269:
270: return $this->featList;
271: }
272:
273: 274: 275:
276: public function archive()
277: {
278: $page = $this->page();
279: $cat = $this->category();
280: if (isset($this->archive[$cat])) {
281: if (isset($this->archive[$cat][$page])) {
282: return $this->archive[$cat][$page];
283: }
284: }
285:
286: $loader = $this->loader()->archive();
287: $loader->addOrder('news_date', 'desc');
288:
289: if ($this->category()) {
290: $loader->addFilter('category', $this->category(), [ 'operator' => 'in' ]);
291: }
292: if ($this->numPerPage()) {
293: $loader->setPage($this->page());
294: $loader->setNumPerPage($this->numPerPage());
295: }
296:
297: $this->archive[$cat][$page] = $loader->load();
298:
299: return $this->archive[$cat][$page];
300: }
301:
302: 303: 304: 305:
306: public function latest()
307: {
308: $entries = $this->entries();
309:
310: if (isset($entries[0])) {
311: return $entries[0];
312: } else {
313:
314: return [];
315: }
316: }
317:
318: 319: 320:
321: public function prev()
322: {
323: if ($this->prevNews) {
324: return $this->prevNews;
325: }
326:
327: return $this->setPrevNext()->prevNews;
328: }
329:
330: 331: 332:
333: public function next()
334: {
335: if ($this->nextNews) {
336: return $this->nextNews;
337: }
338:
339: return $this->setPrevNext()->nextNews;
340: }
341:
342: 343: 344:
345: public function currentPage()
346: {
347: if ($this->currentPage) {
348: return $this->currentPage;
349: }
350: if (!$this->currentNews() || !$this->currentNews()['id']) {
351: $this->currentPage = 1;
352:
353: return 1;
354: }
355: $all = $this->all();
356: $i = 0;
357: foreach ($all as $news) {
358: $i++;
359: if ($news->id() == $this->currentNews()['id']) {
360: break;
361: }
362: }
363:
364: $this->currentPage = $this->numPerPage() ? ceil($i / $this->numPerPage()) : 1;
365:
366: return $this->currentPage;
367: }
368:
369:
370:
371:
372:
373: 374: 375:
376: public function currentNews()
377: {
378: if (!$this->currentNews) {
379: $this->currentNews = $this->latest();
380: }
381:
382: return $this->currentNews;
383: }
384:
385: 386: 387:
388: public function numPerPage()
389: {
390: return $this->numPerPage;
391: }
392:
393: 394: 395:
396: public function entryCycle()
397: {
398: return $this->entryCycle;
399: }
400:
401: 402: 403: 404:
405: public function numNews()
406: {
407: return !!(count($this->entries()));
408: }
409:
410: 411: 412: 413:
414: public function numPages()
415: {
416: return ceil($this->entriesLoader()->loadCount() / $this->numPerPage());
417: }
418:
419: 420: 421: 422:
423: public function hasPager()
424: {
425: return ($this->numPages() > 1);
426: }
427:
428: 429: 430:
431: public function page()
432: {
433: return $this->page;
434: }
435:
436: 437: 438:
439: public function category()
440: {
441: return $this->category;
442: }
443:
444: 445: 446:
447: public function objType()
448: {
449: return $this->objType;
450: }
451:
452: 453: 454:
455: public function featIdent()
456: {
457: return $this->featIdent;
458: }
459:
460: 461: 462:
463: public function loader()
464: {
465: return $this->loader;
466: }
467:
468:
469:
470:
471:
472: 473: 474: 475:
476: public function setCurrentNews($currentNews)
477: {
478: $this->currentNews = $currentNews;
479:
480: return $this;
481: }
482:
483: 484: 485: 486:
487: public function setNumPerPage($numPerPage)
488: {
489: $this->numPerPage = $numPerPage;
490:
491: return $this;
492: }
493:
494: 495: 496: 497:
498: public function setEntryCycle($entryCycle)
499: {
500: $this->entryCycle = $entryCycle;
501:
502: return $this;
503: }
504:
505: 506: 507: 508:
509: public function setPage($page)
510: {
511: $this->page = $page;
512:
513: return $this;
514: }
515:
516: 517: 518: 519:
520: public function setCategory($category)
521: {
522: $this->category = $category;
523:
524: return $this;
525: }
526:
527: 528: 529: 530:
531: public function setObjType($objType)
532: {
533: $this->objType = $objType;
534:
535: return $this;
536: }
537:
538: 539: 540: 541:
542: public function setFeatIdent($featIdent)
543: {
544: $this->featIdent = $featIdent;
545:
546: return $this;
547: }
548:
549: 550: 551: 552:
553: public function setLoader(NewsLoader $loader)
554: {
555: $this->loader = $loader;
556:
557: return $this;
558: }
559:
560:
561:
562:
563:
564: 565: 566: 567:
568: public function setPrevNext()
569: {
570: if ($this->nextNews && $this->prevNews) {
571: return $this;
572: }
573: $entries = $this->entries();
574:
575: $isPrev = false;
576: $isNext = false;
577: $firstNews = false;
578: $lastNews = false;
579:
580:
581: foreach ($entries as $news) {
582:
583: if (!$firstNews) {
584: $firstNews = $news;
585: }
586: $lastNews = $news;
587:
588: if ($news->id() == $this->currentNews()['id']) {
589: $isNext = true;
590: $isPrev = true;
591:
592: continue;
593: }
594: if (!$isPrev) {
595: $this->prevNews = $news;
596: }
597:
598: if ($isNext) {
599: $this->nextNews = $news;
600:
601: $isNext = false;
602: }
603: }
604:
605: if ($this->entryCycle()) {
606: if (!$this->nextNews) {
607: $this->nextNews = $firstNews;
608: }
609:
610: if (!$this->prevNews) {
611: $this->prevNews = $lastNews;
612: }
613: }
614:
615: return $this;
616: }
617: }
618: