Issues (459)

src/util/DateScaleUtils.php (7 issues)

1
<?php
2
3
/**
4
 * JPGraph v4.0.3
5
 */
6
7
namespace Amenadiel\JpGraph\Util;
8
9
/*
10
 * @class DateScaleUtils
11
 * // Description: Help to create a manual date scale
12
 */
13 1
define('DSUTILS_MONTH', 1); // Major and minor ticks on a monthly basis
14 1
define('DSUTILS_MONTH1', 1); // Major and minor ticks on a monthly basis
15 1
define('DSUTILS_MONTH2', 2); // Major ticks on a bi-monthly basis
16 1
define('DSUTILS_MONTH3', 3); // Major icks on a tri-monthly basis
17 1
define('DSUTILS_MONTH6', 4); // Major on a six-monthly basis
18 1
define('DSUTILS_WEEK1', 5); // Major ticks on a weekly basis
19 1
define('DSUTILS_WEEK2', 6); // Major ticks on a bi-weekly basis
20 1
define('DSUTILS_WEEK4', 7); // Major ticks on a quod-weekly basis
21 1
define('DSUTILS_DAY1', 8); // Major ticks on a daily basis
22 1
define('DSUTILS_DAY2', 9); // Major ticks on a bi-daily basis
23 1
define('DSUTILS_DAY4', 10); // Major ticks on a qoud-daily basis
24 1
define('DSUTILS_YEAR1', 11); // Major ticks on a yearly basis
25 1
define('DSUTILS_YEAR2', 12); // Major ticks on a bi-yearly basis
26 1
define('DSUTILS_YEAR5', 13); // Major ticks on a five-yearly basis
27
28
class DateScaleUtils
29
{
30
    public static $iMin = 0;
31
    public static $iMax = 0;
32
33
    private static $starthour;
34
    private static $startmonth;
35
    private static $startday;
36
    private static $startyear;
37
    private static $endmonth;
38
    private static $endyear;
39
    private static $endday;
40
    private static $tickPositions    = [];
41
    private static $minTickPositions = [];
42
    private static $iUseWeeks        = true;
43
44
    public static function UseWeekFormat($aFlg)
45
    {
46
        self::$iUseWeeks = $aFlg;
47
    }
48
49 1
    public static function doYearly($aType, $aMinor = false)
50
    {
51 1
        $i = 0;
52 1
        $j = 0;
53 1
        $m = self::$startmonth;
54 1
        $y = self::$startyear;
55
56 1
        if (self::$startday == 1) {
57
            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
58
        }
59 1
        ++$m;
60
61
        switch ($aType) {
62 1
            case DSUTILS_YEAR1:
63
                for ($y = self::$startyear; $y <= self::$endyear; ++$y) {
64
                    if ($aMinor) {
65
                        while ($m <= 12) {
66
                            if (!($y == self::$endyear && $m > self::$endmonth)) {
67
                                self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y);
68
                            }
69
                            ++$m;
70
                        }
71
                        $m = 1;
72
                    }
73
                    self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y);
74
                }
75
76
                break;
77 1
            case DSUTILS_YEAR2:
78 1
                $y = self::$startyear;
79 1
                while ($y <= self::$endyear) {
80 1
                    self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y);
81 1
                    for ($k = 0; $k < 1; ++$k) {
82 1
                        ++$y;
83 1
                        if ($aMinor) {
84
                            self::$minTickPositions[$j++] = mktime(0, 0, 0, 1, 1, $y);
85
                        }
86
                    }
87 1
                    ++$y;
88
                }
89
90 1
                break;
91
            case DSUTILS_YEAR5:
92
                $y = self::$startyear;
93
                while ($y <= self::$endyear) {
94
                    self::$tickPositions[$i++] = mktime(0, 0, 0, 1, 1, $y);
95
                    for ($k = 0; $k < 4; ++$k) {
96
                        ++$y;
97
                        if ($aMinor) {
98
                            self::$minTickPositions[$j++] = mktime(0, 0, 0, 1, 1, $y);
99
                        }
100
                    }
101
                    ++$y;
102
                }
103
104
                break;
105
        }
106 1
    }
107
108
    public static function doDaily($aType, $aMinor = false)
109
    {
110
        $m = self::$startmonth;
111
        $y = self::$startyear;
112
        $d = self::$startday;
113
        $h = self::$starthour;
114
        $i = 0;
115
        $j = 0;
116
117
        if ($h == 0) {
118
            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, $d, $y);
119
        }
120
        $t = mktime(0, 0, 0, $m, $d, $y);
121
122
        switch ($aType) {
123
            case DSUTILS_DAY1:
124
                while ($t <= self::$iMax) {
125
                    $t                         = strtotime('+1 day', $t);
126
                    self::$tickPositions[$i++] = $t;
127
                    if ($aMinor) {
128
                        self::$minTickPositions[$j++] = strtotime('+12 hours', $t);
129
                    }
130
                }
131
132
                break;
133
            case DSUTILS_DAY2:
134
                while ($t <= self::$iMax) {
135
                    $t = strtotime('+1 day', $t);
136
                    if ($aMinor) {
137
                        self::$minTickPositions[$j++] = $t;
138
                    }
139
                    $t                         = strtotime('+1 day', $t);
140
                    self::$tickPositions[$i++] = $t;
141
                }
142
143
                break;
144
            case DSUTILS_DAY4:
145
                while ($t <= self::$iMax) {
146
                    for ($k = 0; $k < 3; ++$k) {
147
                        $t = strtotime('+1 day', $t);
148
                        if ($aMinor) {
149
                            self::$minTickPositions[$j++] = $t;
150
                        }
151
                    }
152
                    $t                         = strtotime('+1 day', $t);
153
                    self::$tickPositions[$i++] = $t;
154
                }
155
156
                break;
157
        }
158
    }
159
160
    public static function doWeekly($aType, $aMinor = false)
161
    {
162
        $hpd = 3600 * 24;
163
        $hpw = 3600 * 24 * 7;
164
        // Find out week number of min date
165
        $thursday  = self::$iMin + $hpd * (3 - (date('w', self::$iMin) + 6) % 7);
166
        $week      = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, date('Y', $thursday)))) % 7) / 7;
0 ignored issues
show
The assignment to $week is dead and can be removed.
Loading history...
date('Y', $thursday) of type string is incompatible with the type integer expected by parameter $year of mktime(). ( Ignorable by Annotation )

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

166
        $week      = 1 + (date('z', $thursday) - (11 - date('w', mktime(0, 0, 0, 1, 1, /** @scrutinizer ignore-type */ date('Y', $thursday)))) % 7) / 7;
Loading history...
167
        $daynumber = date('w', self::$iMin);
168
        if ($daynumber == 0) {
169
            $daynumber = 7;
170
        }
171
172
        $m = self::$startmonth;
173
        $y = self::$startyear;
174
        $d = self::$startday;
175
        $i = 0;
176
        $j = 0;
177
        // The assumption is that the weeks start on Monday. If the first day
178
        // is later in the week then the first week tick has to be on the following
179
        // week.
180
        if ($daynumber == 1) {
181
            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, $d, $y);
182
            $t                         = mktime(0, 0, 0, $m, $d, $y) + $hpw;
183
        } else {
184
            $t = mktime(0, 0, 0, $m, $d, $y) + $hpd * (8 - $daynumber);
185
        }
186
187
        switch ($aType) {
188
            case DSUTILS_WEEK1:
189
                $cnt = 0;
190
191
                break;
192
            case DSUTILS_WEEK2:
193
                $cnt = 1;
194
195
                break;
196
            case DSUTILS_WEEK4:
197
                $cnt = 3;
198
199
                break;
200
        }
201
        while ($t <= self::$iMax) {
202
            self::$tickPositions[$i++] = $t;
203
            for ($k = 0; $k < $cnt; ++$k) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $cnt does not seem to be defined for all execution paths leading up to this point.
Loading history...
204
                $t += $hpw;
205
                if ($aMinor) {
206
                    self::$minTickPositions[$j++] = $t;
207
                }
208
            }
209
            $t += $hpw;
210
        }
211
    }
212
213
    public static function doMonthly($aType, $aMinor = false)
214
    {
215
        $monthcount = 0;
216
        $m          = self::$startmonth;
217
        $y          = self::$startyear;
218
        $i          = 0;
219
        $j          = 0;
220
221
        // Skip the first month label if it is before the startdate
222
        if (self::$startday == 1) {
223
            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
224
            $monthcount                = 1;
225
        }
226
        if ($aType == 1) {
227
            if (self::$startday < 15) {
228
                self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 15, $y);
229
            }
230
        }
231
        ++$m;
232
233
        // Loop through all the years included in the scale
234
        for ($y = self::$startyear; $y <= self::$endyear; ++$y) {
235
            // Loop through all the months. There are three cases to consider:
236
            // 1. We are in the first year and must start with the startmonth
237
            // 2. We are in the end year and we must stop at last month of the scale
238
            // 3. A year in between where we run through all the 12 months
239
            $stopmonth = $y == self::$endyear ? self::$endmonth : 12;
240
            while ($m <= $stopmonth) {
241
                switch ($aType) {
242
                    case DSUTILS_MONTH1:
243
                        // Set minor tick at the middle of the month
244
                        if ($aMinor) {
245
                            if ($m <= $stopmonth) {
246
                                if (!($y == self::$endyear && $m == $stopmonth && self::$endday < 15)) {
247
                                    self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 15, $y);
248
                                }
249
                            }
250
                        }
251
                        // Major at month
252
                        // Get timestamp of first hour of first day in each month
253
                        self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
254
255
                        break;
256
                    case DSUTILS_MONTH2:
257
                        if ($aMinor) {
258
                            // Set minor tick at start of each month
259
                            self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y);
260
                        }
261
262
                        // Major at every second month
263
                        // Get timestamp of first hour of first day in each month
264
                        if ($monthcount % 2 == 0) {
265
                            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
266
                        }
267
268
                        break;
269
                    case DSUTILS_MONTH3:
270
                        if ($aMinor) {
271
                            // Set minor tick at start of each month
272
                            self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y);
273
                        }
274
                        // Major at every third month
275
                        // Get timestamp of first hour of first day in each month
276
                        if ($monthcount % 3 == 0) {
277
                            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
278
                        }
279
280
                        break;
281
                    case DSUTILS_MONTH6:
282
                        if ($aMinor) {
283
                            // Set minor tick at start of each month
284
                            self::$minTickPositions[$j++] = mktime(0, 0, 0, $m, 1, $y);
285
                        }
286
                        // Major at every third month
287
                        // Get timestamp of first hour of first day in each month
288
                        if ($monthcount % 6 == 0) {
289
                            self::$tickPositions[$i++] = mktime(0, 0, 0, $m, 1, $y);
290
                        }
291
292
                        break;
293
                }
294
                ++$m;
295
                ++$monthcount;
296
            }
297
            $m = 1;
298
        }
299
300
        // For the case where all dates are within the same month
301
        // we want to make sure we have at least two ticks on the scale
302
        // since the scale want work properly otherwise
303
        if (self::$startmonth == self::$endmonth && self::$startyear == self::$endyear && $aType == 1) {
304
            self::$tickPositions[$i++] = mktime(0, 0, 0, self::$startmonth + 1, 1, self::$startyear);
305
        }
306
307
        return [self::$tickPositions, self::$minTickPositions];
308
    }
309
310 1
    public static function GetTicks($aData, $aType = 1, $aMinor = false, $aEndPoints = false)
311
    {
312 1
        $n = safe_count($aData);
313
314 1
        return self::GetTicksFromMinMax($aData[0], $aData[$n - 1], $aType, $aMinor, $aEndPoints);
315
    }
316
317
    public static function GetAutoTicks($aMin, $aMax, $aMaxTicks = 10, $aMinor = false)
318
    {
319
        $diff = $aMax - $aMin;
320
        $spd  = 3600 * 24;
321
        $spw  = $spd * 7;
322
        $spm  = $spd * 30;
323
        $spy  = $spd * 352;
324
325
        if (self::$iUseWeeks) {
326
            $w = 'W';
327
        } else {
328
            $w = 'd M';
329
        }
330
331
        // Decision table for suitable scales
332
        // First value: Main decision point
333
        // Second value: Array of formatting depending on divisor for wanted max number of ticks. <divisor><formatting><format-string>,..
334
        $tt = [
335
            [$spw, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', -1, DSUTILS_DAY4, 'd M']],
336
            [$spm, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', 4, DSUTILS_DAY4, 'd M', 7, DSUTILS_WEEK1, $w, -1, DSUTILS_WEEK2, $w]],
337
            [$spy, [1, DSUTILS_DAY1, 'd M', 2, DSUTILS_DAY2, 'd M', 4, DSUTILS_DAY4, 'd M', 7, DSUTILS_WEEK1, $w, 14, DSUTILS_WEEK2, $w, 30, DSUTILS_MONTH1, 'M', 60, DSUTILS_MONTH2, 'M', -1, DSUTILS_MONTH3, 'M']],
338
            [-1, [30, DSUTILS_MONTH1, 'M-Y', 60, DSUTILS_MONTH2, 'M-Y', 90, DSUTILS_MONTH3, 'M-Y', 180, DSUTILS_MONTH6, 'M-Y', 352, DSUTILS_YEAR1, 'Y', 704, DSUTILS_YEAR2, 'Y', -1, DSUTILS_YEAR5, 'Y']], ];
339
340
        $ntt = safe_count($tt);
341
        $nd  = floor($diff / $spd);
342
        for ($i = 0; $i < $ntt; ++$i) {
343
            if ($diff <= $tt[$i][0] || $i == $ntt - 1) {
344
                $t = $tt[$i][1];
345
                $n = safe_count($t) / 3;
346
                for ($j = 0; $j < $n; ++$j) {
347
                    if ($nd / $t[3 * $j] <= $aMaxTicks || $j == $n - 1) {
348
                        $type                                   = $t[3 * $j + 1];
349
                        $fs                                     = $t[3 * $j + 2];
350
                        list($tickPositions, $minTickPositions) = self::GetTicksFromMinMax($aMin, $aMax, $type, $aMinor);
351
352
                        return [$fs, $tickPositions, $minTickPositions, $type];
353
                    }
354
                }
355
            }
356
        }
357
    }
358
359 1
    public static function GetTicksFromMinMax($aMin, $aMax, $aType, $aMinor = false, $aEndPoints = false)
360
    {
361 1
        self::$starthour  = date('G', $aMin);
362 1
        self::$startmonth = date('n', $aMin);
363 1
        self::$startday   = date('j', $aMin);
364 1
        self::$startyear  = date('Y', $aMin);
365 1
        self::$endmonth   = date('n', $aMax);
366 1
        self::$endyear    = date('Y', $aMax);
367 1
        self::$endday     = date('j', $aMax);
368 1
        self::$iMin       = $aMin;
369 1
        self::$iMax       = $aMax;
370
371 1
        if ($aType <= DSUTILS_MONTH6) {
372
            self::doMonthly($aType, $aMinor);
373 1
        } elseif ($aType <= DSUTILS_WEEK4) {
374
            self::doWeekly($aType, $aMinor);
375 1
        } elseif ($aType <= DSUTILS_DAY4) {
376
            self::doDaily($aType, $aMinor);
377 1
        } elseif ($aType <= DSUTILS_YEAR5) {
378 1
            self::doYearly($aType, $aMinor);
379
        } else {
380
            JpGraphError::RaiseL(24003);
381
        }
382
        // put a label at the very left data pos
383 1
        if ($aEndPoints) {
384
            $tickPositions[$i++] = $aData[0];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$tickPositions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $tickPositions = array(); before regardless.
Loading history...
Comprehensibility Best Practice introduced by
The variable $aData seems to be never defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable $i seems to be never defined.
Loading history...
385
        }
386
387
        // put a label at the very right data pos
388 1
        if ($aEndPoints) {
389
            $tickPositions[$i] = $aData[$n - 1];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $n seems to be never defined.
Loading history...
390
        }
391
392 1
        return [self::$tickPositions, self::$minTickPositions];
393
    }
394
}
395