Test Failed
Push — master ( dc68d1...1f5199 )
by Mathieu
02:31
created

EventManager::featList()   C

Complexity

Conditions 14
Paths 5

Size

Total Lines 56
Code Lines 37

Duplication

Lines 56
Ratio 100 %

Importance

Changes 0
Metric Value
dl 56
loc 56
rs 6.6598
c 0
b 0
f 0
cc 14
eloc 37
nc 5
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 View Code Duplication
    public function __construct(array $data)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function entry($id = null)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
236
    {
237
        if (!$id) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $id of type integer|null is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
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);
0 ignored issues
show
Documentation introduced by
$this->objType() is of type object, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->all of type Charcoal\Cms\EventInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
259
            return $this->all;
260
        }
261
262
        $this->all = $this->loader()->all()
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->loader()->all()->...t_date', 'asc')->load() can also be of type object. However, the property $all is declared as type array<integer,object<Cha...al\Cms\EventInterface>>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
263
            ->addOrder('start_date', 'asc')->load();
264
265
        return $this->all;
266
    }
267
268
    /**
269
     * @return CategoryInterface[]|Collection The category collection.
270
     */
271 View Code Duplication
    public function loadCategoryItems()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function featList(array $options = [])
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
300
    {
301
        if ($this->featList) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->featList of type Charcoal\Cms\EventInterface[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
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'] ?: '';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$filter was never initialized. Although not strictly required by PHP, it is generally a good practice to add $filter = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
334
                            $filter[] = $f['val'] ?: '';
0 ignored issues
show
Bug introduced by
The variable $filter does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $loader->load() can also be of type object. However, the property $featList is declared as type array<integer,object<Cha...al\Cms\EventInterface>>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
352
353
        return $this->featList;
354
    }
355
356
    /**
357
     * @return EventInterface[]|Collection
358
     */
359 View Code Duplication
    public function archive()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function latest()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
    public function currentPage()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->numPerPage() ? ce...this->numPerPage()) : 1 can also be of type double. However, the property $currentPage is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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 View Code Duplication
        if (isset($map[$year][$month][$day])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->latest() can also be of type array. However, the property $currentEvent is declared as type object<Charcoal\Cms\EventInterface>. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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 View Code Duplication
    public function numPages()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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());
0 ignored issues
show
Documentation Bug introduced by
The property $numPage was declared of type integer, but ceil($count / $this->numPerPage()) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
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;
0 ignored issues
show
Documentation Bug introduced by
It seems like $date of type object<DateTime> is incompatible with the declared type object<Charcoal\Cms\Service\Manager\datetime> of property $date.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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 View Code Duplication
    public function setPrevNext()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->mapEvents of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
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 View Code Duplication
                if (!isset($out[$year][$month][$day])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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