Passed
Pull Request — master (#2)
by tsms
01:30
created

Week   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 387
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 165
dl 0
loc 387
rs 7.92
c 0
b 0
f 0
wmc 51

12 Methods

Rating   Name   Duplication   Size   Complexity  
B nextWeek() 0 19 8
A setTimestamp() 0 25 1
B prevWeek() 0 19 8
B thisWeek() 0 32 9
A __construct() 0 25 1
A thisYear() 0 20 4
A setLast() 0 3 1
B build() 0 39 7
A setFirst() 0 3 1
A findFirstDay() 0 8 4
A getHelper() 0 3 1
A setSelection() 0 14 6

How to fix   Complexity   

Complex Class

Complex classes like Week often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Week, and based on these observations, apply Extract Interface, too.

1
<?php
2
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4
/**
5
 * Contains the Calendar_Week class
6
 *
7
 * PHP versions 4 and 5
8
 *
9
 * LICENSE: Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. The name of the author may not be used to endorse or promote products
17
 *    derived from this software without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
20
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22
 * IN NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY
23
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * @category  Date and Time
31
 * @package   Calendar
32
 * @author    Harry Fuecks <[email protected]>
33
 * @author    Lorenzo Alberton <[email protected]>
34
 * @copyright 2003-2007 Harry Fuecks, Lorenzo Alberton
35
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
36
 * @version   CVS: $Id$
37
 * @link      http://pear.php.net/package/Calendar
38
 */
39
namespace Pear\Calendar;
40
41
use Pear\Calendar\Table\Helper;
42
43
/**
44
 * Represents a Week and builds Days in tabular format<br>
45
 * <code>
46
 * require_once 'Calendar/Week.php';
47
 * $Week = new Calendar_Week(2003, 10, 1); Oct 2003, 1st tabular week
48
 * echo '<tr>';
49
 * while ($Day = & $Week->fetch()) {
50
 *     if ($Day->isEmpty()) {
51
 *         echo '<td>&nbsp;</td>';
52
 *     } else {
53
 *         echo '<td>'.$Day->thisDay().'</td>';
54
 *      }
55
 * }
56
 * echo '</tr>';
57
 * </code>
58
 *
59
 * @category  Date and Time
60
 * @package   Calendar
61
 * @author    Harry Fuecks <[email protected]>
62
 * @author    Lorenzo Alberton <[email protected]>
63
 * @copyright 2003-2007 Harry Fuecks, Lorenzo Alberton
64
 * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
65
 * @link      http://pear.php.net/package/Calendar
66
 */
67
class Week extends Calendar
68
{
69
    /**
70
     * Instance of Calendar_Table_Helper
0 ignored issues
show
Bug introduced by
The type Pear\Calendar\Calendar_Table_Helper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
71
     * @var Calendar_Table_Helper
72
     * @access private
73
     */
74
    var $tableHelper;
75
76
    /**
77
     * Stores the timestamp of the first day of this week
78
     * @access private
79
     * @var object
80
     */
81
    var $thisWeek;
82
83
    /**
84
     * Stores the timestamp of first day of previous week
85
     * @access private
86
     * @var object
87
     */
88
    var $prevWeek;
89
90
    /**
91
     * Stores the timestamp of first day of next week
92
     * @access private
93
     * @var object
94
     */
95
    var $nextWeek;
96
97
    /**
98
     * Used by build() to set empty days
99
     * @access private
100
     * @var boolean
101
     */
102
    var $firstWeek = false;
103
104
    /**
105
     * Used by build() to set empty days
106
     * @access private
107
     * @var boolean
108
     */
109
    var $lastWeek = false;
110
111
    /**
112
     * First day of the week (0=sunday, 1=monday...)
113
     * @access private
114
     * @var boolean
115
     */
116
    var $firstDay = 1;
117
118
    /**
119
     * Constructs Week
120
     *
121
     * @param int $y        year e.g. 2003
122
     * @param int $m        month e.g. 5
123
     * @param int $d        a day of the desired week
124
     * @param int $firstDay (optional) first day of week (e.g. 0 for Sunday, 2 for Tuesday etc.)
125
     *
126
     * @access public
127
     */
128
    function __construct($y, $m, $d, $firstDay = null)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
129
    {
130
        parent::__construct($y, $m, $d);
131
        $this->firstDay    = $this->defineFirstDayOfWeek($firstDay);
0 ignored issues
show
Documentation Bug introduced by
The property $firstDay was declared of type boolean, but $this->defineFirstDayOfWeek($firstDay) is of type integer. 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...
132
        $this->tableHelper = new Helper($this, $this->firstDay);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Pear\Calendar\Table\...$this, $this->firstDay) of type Pear\Calendar\Table\Helper is incompatible with the declared type Pear\Calendar\Calendar_Table_Helper of property $tableHelper.

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...
133
        $this->thisWeek    = $this->tableHelper->getWeekStart($y, $m, $d, $this->firstDay);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->tableHelper->getW...m, $d, $this->firstDay) of type integer is incompatible with the declared type object of property $thisWeek.

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...
134
        $this->prevWeek    = $this->tableHelper->getWeekStart(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->tableHelper->getW...ay()), $this->firstDay) of type integer is incompatible with the declared type object of property $prevWeek.

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...
135
            $y, 
136
            $m, 
137
            $d - $this->cE->getDaysInWeek(
138
                $this->thisYear(),
139
                $this->thisMonth(),
140
                $this->thisDay()
141
            ), 
142
            $this->firstDay
143
        );
144
        $this->nextWeek = $this->tableHelper->getWeekStart(
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->tableHelper->getW...ay()), $this->firstDay) of type integer is incompatible with the declared type object of property $nextWeek.

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...
145
            $y, 
146
            $m, 
147
            $d + $this->cE->getDaysInWeek(
148
                $this->thisYear(),
149
                $this->thisMonth(),
150
                $this->thisDay()
151
            ), 
152
            $this->firstDay
153
        );
154
    }
155
156
    /**
157
     * Defines the calendar by a timestamp (Unix or ISO-8601), replacing values
158
     * passed to the constructor
159
     *
160
     * @param int|string $ts Unix or ISO-8601 timestamp
161
     *
162
     * @return void
163
     * @access public
164
     */
165
    function setTimestamp($ts)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
166
    {
167
        parent::setTimestamp($ts);
168
        $this->thisWeek = $this->tableHelper->getWeekStart(
169
            $this->year, $this->month, $this->day, $this->firstDay
170
        );
171
        $this->prevWeek = $this->tableHelper->getWeekStart(
172
            $this->year, 
173
            $this->month, 
174
            $this->day - $this->cE->getDaysInWeek(
175
                $this->thisYear(),
176
                $this->thisMonth(),
177
                $this->thisDay()
178
            ), 
179
            $this->firstDay
180
        );
181
        $this->nextWeek = $this->tableHelper->getWeekStart(
182
            $this->year, 
183
            $this->month, 
184
            $this->day + $this->cE->getDaysInWeek(
185
                $this->thisYear(),
186
                $this->thisMonth(),
187
                $this->thisDay()
188
            ), 
189
            $this->firstDay
190
        );
191
    }
192
193
    /**
194
     * Builds Calendar_Day objects for this Week
195
     *
196
     * @param array $sDates (optional) Calendar_Day objects representing selected dates
197
     *
198
     * @return boolean
199
     * @access public
200
     */
201
    function build($sDates = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
202
    {
203
        include_once CALENDAR_ROOT.'Day.php';
204
        $year  = $this->cE->stampToYear($this->thisWeek);
205
        $month = $this->cE->stampToMonth($this->thisWeek);
206
        $day   = $this->cE->stampToDay($this->thisWeek);
207
        $end   = $this->cE->getDaysInWeek(
208
            $this->thisYear(),
209
            $this->thisMonth(),
210
            $this->thisDay()
211
        );
212
213
        for ($i=1; $i <= $end; $i++) {
214
            $stamp = $this->cE->dateToStamp($year, $month, $day++);
215
            $this->children[$i] = new Day(
216
                $this->cE->stampToYear($stamp),
217
                $this->cE->stampToMonth($stamp),
218
                $this->cE->stampToDay($stamp)
219
            );
220
        }
221
222
        //set empty days (@see Calendar_Month_Weeks::build())
223
        if ($this->firstWeek) {
224
            $eBefore = $this->tableHelper->getEmptyDaysBefore();
225
            for ($i=1; $i <= $eBefore; $i++) {
226
                $this->children[$i]->setEmpty();
227
            }
228
        }
229
        if ($this->lastWeek) {
230
            $eAfter = $this->tableHelper->getEmptyDaysAfterOffset();
231
            for ($i = $eAfter+1; $i <= $end; $i++) {
232
                $this->children[$i]->setEmpty();
233
            }
234
        }
235
236
        if (count($sDates) > 0) {
237
            $this->setSelection($sDates);
238
        }
239
        return true;
240
    }
241
242
    /**
243
     * Set as first week of the month
244
     *
245
     * @param boolean $state whether it's first or not
246
     *
247
     * @return void
248
     * @access private
249
     */
250
    function setFirst($state = true)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
251
    {
252
        $this->firstWeek = $state;
253
    }
254
255
    /**
256
     * Set as last week of the month
257
     *
258
     * @param boolean $state whether it's lasst or not
259
     *
260
     * @return void
261
     * @access private
262
     */
263
    function setLast($state = true)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
264
    {
265
        $this->lastWeek = $state;
266
    }
267
268
    /**
269
     * Called from build()
270
     *
271
     * @param array $sDates Calendar_Day objects representing selected dates
272
     *
273
     * @return void
274
     * @access private
275
     */
276
    function setSelection($sDates)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
277
    {
278
        foreach ($sDates as $sDate) {
279
            foreach ($this->children as $key => $child) {
280
                if ($child->thisDay() == $sDate->thisDay() &&
281
                    $child->thisMonth() == $sDate->thisMonth() &&
282
                    $child->thisYear() == $sDate->thisYear()
283
                ) {
284
                    $this->children[$key] = $sDate;
285
                    $this->children[$key]->setSelected();
286
                }
287
            }
288
        }
289
        reset($this->children);
290
    }
291
292
    /**
293
     * Returns the value for this year
294
     *
295
     * When a on the first/last week of the year, the year of the week is
296
     * calculated according to ISO-8601
297
     *
298
     * @param string $format return value format ['int' | 'timestamp' | 'object' | 'array']
299
     *
300
     * @return int e.g. 2003 or timestamp
301
     * @access public
302
     */
303
    function thisYear($format = 'int')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
304
    {
305
        if (null !== $this->thisWeek) {
306
            $tmp_cal = new Calendar();
307
            $tmp_cal->setTimestamp($this->thisWeek);
0 ignored issues
show
Bug introduced by
$this->thisWeek of type object is incompatible with the type integer|string expected by parameter $ts of Pear\Calendar\Calendar::setTimestamp(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

307
            $tmp_cal->setTimestamp(/** @scrutinizer ignore-type */ $this->thisWeek);
Loading history...
308
            $first_dow = $tmp_cal->thisDay('array');
309
            $days_in_week = $tmp_cal->cE->getDaysInWeek($tmp_cal->year, $tmp_cal->month, $tmp_cal->day);
310
            $tmp_cal->day += $days_in_week;
311
            $last_dow  = $tmp_cal->thisDay('array');
312
313
            if ($first_dow['year'] == $last_dow['year']) {
314
                return $first_dow['year'];
315
            }
316
317
            if ($last_dow['day'] > floor($days_in_week / 2)) {
318
                return $last_dow['year'];
319
            }
320
            return $first_dow['year'];
321
        }
322
        return parent::thisYear();
323
    }
324
325
    /**
326
     * Gets the value of the previous week, according to the requested format
327
     *
328
     * @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array']
329
     *
330
     * @return mixed
331
     * @access public
332
     */
333
    function prevWeek($format = 'n_in_month')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
334
    {
335
        switch (strtolower($format)) {
336
        case 'int':
337
        case 'n_in_month':
338
            return ($this->firstWeek) ? null : $this->thisWeek('n_in_month') -1;
339
        case 'n_in_year':
340
            return $this->cE->getWeekNInYear(
341
                $this->cE->stampToYear($this->prevWeek),
342
                $this->cE->stampToMonth($this->prevWeek),
343
                $this->cE->stampToDay($this->prevWeek));
344
        case 'array':
345
            return $this->toArray($this->prevWeek);
346
        case 'object':
347
            include_once CALENDAR_ROOT.'Factory.php';
348
            return Factory::createByTimestamp('Week', $this->prevWeek);
0 ignored issues
show
Bug Best Practice introduced by
The method Pear\Calendar\Factory::createByTimestamp() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

348
            return Factory::/** @scrutinizer ignore-call */ createByTimestamp('Week', $this->prevWeek);
Loading history...
349
        case 'timestamp':
350
        default:
351
            return $this->prevWeek;
352
        }
353
    }
354
355
    /**
356
     * Gets the value of the current week, according to the requested format
357
     *
358
     * @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array']
359
     *
360
     * @return mixed
361
     * @access public
362
     */
363
    function thisWeek($format = 'n_in_month')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
364
    {
365
        switch (strtolower($format)) {
366
        case 'int':
367
        case 'n_in_month':
368
            if ($this->firstWeek) {
369
                return 1;
370
            }
371
            if ($this->lastWeek) {
372
                return $this->cE->getWeeksInMonth(
373
                    $this->thisYear(),
374
                    $this->thisMonth(),
375
                    $this->firstDay);
376
            }
377
            return $this->cE->getWeekNInMonth(
378
                $this->thisYear(),
379
                $this->thisMonth(),
380
                $this->thisDay(),
381
                $this->firstDay);
382
        case 'n_in_year':
383
            return $this->cE->getWeekNInYear(
384
                $this->cE->stampToYear($this->thisWeek),
385
                $this->cE->stampToMonth($this->thisWeek),
386
                $this->cE->stampToDay($this->thisWeek));
387
        case 'array':
388
            return $this->toArray($this->thisWeek);
389
        case 'object':
390
            include_once CALENDAR_ROOT.'Factory.php';
391
            return Factory::createByTimestamp('Week', $this->thisWeek);
0 ignored issues
show
Bug Best Practice introduced by
The method Pear\Calendar\Factory::createByTimestamp() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

391
            return Factory::/** @scrutinizer ignore-call */ createByTimestamp('Week', $this->thisWeek);
Loading history...
392
        case 'timestamp':
393
        default:
394
            return $this->thisWeek;
395
        }
396
    }
397
398
    /**
399
     * Gets the value of the following week, according to the requested format
400
     *
401
     * @param string $format ['timestamp' | 'n_in_month' | 'n_in_year' | 'array']
402
     *
403
     * @return mixed
404
     * @access public
405
     */
406
    function nextWeek($format = 'n_in_month')
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
407
    {
408
        switch (strtolower($format)) {
409
        case 'int':
410
        case 'n_in_month':
411
            return ($this->lastWeek) ? null : $this->thisWeek('n_in_month') +1;
412
        case 'n_in_year':
413
            return $this->cE->getWeekNInYear(
414
                $this->cE->stampToYear($this->nextWeek),
415
                $this->cE->stampToMonth($this->nextWeek),
416
                $this->cE->stampToDay($this->nextWeek));
417
        case 'array':
418
            return $this->toArray($this->nextWeek);
419
        case 'object':
420
            include_once CALENDAR_ROOT.'Factory.php';
421
            return Factory::createByTimestamp('Week', $this->nextWeek);
0 ignored issues
show
Bug Best Practice introduced by
The method Pear\Calendar\Factory::createByTimestamp() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

421
            return Factory::/** @scrutinizer ignore-call */ createByTimestamp('Week', $this->nextWeek);
Loading history...
422
        case 'timestamp':
423
        default:
424
            return $this->nextWeek;
425
        }
426
    }
427
428
    /**
429
     * Returns the instance of Calendar_Table_Helper.
430
     * Called from Calendar_Validator::isValidWeek
431
     *
432
     * @return Calendar_Table_Helper
433
     * @access protected
434
     */
435
    function & getHelper()
436
    {
437
        return $this->tableHelper;
438
    }
439
440
    /**
441
     * Makes sure theres a value for $this->day
442
     *
443
     * @return void
444
     * @access private
445
     */
446
    function findFirstDay()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
447
    {
448
        if (!count($this->children) > 0) {
449
            $this->build();
450
            foreach ($this->children as $Day) {
451
                if (!$Day->isEmpty()) {
452
                    $this->day = $Day->thisDay();
453
                    break;
454
                }
455
            }
456
        }
457
    }
458
}
459