Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
126 / 126
100.00% covered (success)
100.00%
9 / 9
CRAP
100.00% covered (success)
100.00%
1 / 1
SequenceService
100.00% covered (success)
100.00%
126 / 126
100.00% covered (success)
100.00%
9 / 9
37
100.00% covered (success)
100.00%
1 / 1
 fill
100.00% covered (success)
100.00%
24 / 24
100.00% covered (success)
100.00%
1 / 1
11
 hours
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 date
100.00% covered (success)
100.00%
35 / 35
100.00% covered (success)
100.00%
1 / 1
7
 days
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
5
 weeks
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 months
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 daysOfWeek
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dayOfMonth
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 integer
100.00% covered (success)
100.00%
37 / 37
100.00% covered (success)
100.00%
1 / 1
9
1<?php
2
3namespace Drupal\visitors\Service;
4
5/**
6 * Fills missing sequence in the view results.
7 */
8class SequenceService {
9
10  /**
11   * Fills the view results missing sequence.
12   */
13  public static function fill($result) {
14    if (empty($result)) {
15      return $result;
16    }
17
18    $row = $result[0];
19    foreach (get_object_vars($row) as $key => $value) {
20      switch ($key) {
21
22        case 'visitors_hour':
23        case 'visitors_visitor_localtime':
24          $result = self::hours($result, $key);
25          break;
26
27        case 'visitors_day_of_month':
28          $result = self::dayOfMonth($result, $key);
29          break;
30
31        case 'visitors_day_of_week':
32          $result = self::daysOfWeek($result, $key);
33          break;
34
35        case 'visitors_day':
36          $result = self::days($result, $key);
37          break;
38
39        case 'visitors_week':
40          $result = self::weeks($result, $key);
41          break;
42
43        case 'visitors_month':
44          $result = self::months($result, $key);
45          break;
46
47        default:
48          break;
49      }
50    }
51
52    return $result;
53  }
54
55  /**
56   * Fills the missing hours in the result.
57   */
58  protected static function hours($result, $field) {
59    return self::integer($result, $field, 24);
60  }
61
62  /**
63   * Fills the missing date in the result.
64   */
65  protected static function date($result, $field, $max) {
66
67    $rows = [];
68    $exclude_fields = [
69      'index',
70      '_entity',
71      '_relationship_entities',
72      $field,
73    ];
74    $index = 0;
75    $expected = $result[0]->{$field};
76    $year = (int) substr($expected, 0, 4);
77    $month = (int) substr($expected, 4, 2);
78    foreach ($result as $i => $row) {
79      while ($expected < $row->{$field}) {
80        $clone = clone $row;
81        $clone->{$field} = $expected;
82        $clone->index = $index;
83
84        foreach (get_object_vars($clone) as $key => $value) {
85          if (in_array($key, $exclude_fields)) {
86            continue;
87          }
88          $clone->{$key} = '0';
89        }
90
91        $rows[] = $clone;
92        $index += 1;
93        $month += 1;
94        if ($month > $max) {
95          $month = 1;
96          $year += 1;
97        }
98        $expected = $year . str_pad($month, 2, '0', STR_PAD_LEFT);
99
100      }
101      $row->index = $index;
102
103      $index += 1;
104      $month += 1;
105      if ($month > $max) {
106        $month = 1;
107        $year += 1;
108      }
109      $expected = $year . str_pad($month, 2, '0', STR_PAD_LEFT);
110      $rows[] = $row;
111    }
112
113    return $rows;
114  }
115
116  /**
117   * Fills the missing days in the result.
118   */
119  protected static function days($result, $field) {
120    $format = 'Y-m-d';
121    $increment = '+1 day';
122    $rows = [];
123    $exclude_fields = [
124      'index',
125      '_entity',
126      '_relationship_entities',
127      $field,
128    ];
129    $index = 0;
130    $expected = $result[0]->{$field};
131    foreach ($result as $i => $row) {
132      while ($expected < $row->{$field}) {
133        $clone = clone $row;
134        $clone->{$field} = $expected;
135        $clone->index = $index;
136
137        foreach (get_object_vars($clone) as $key => $value) {
138          if (in_array($key, $exclude_fields)) {
139            continue;
140          }
141          $clone->{$key} = '0';
142        }
143
144        $rows[] = $clone;
145        $expected = date($format, strtotime($increment, strtotime($expected)));
146        $index += 1;
147      }
148
149      $expected = date($format, strtotime($increment, strtotime($expected)));
150      $rows[] = $row;
151    }
152
153    return $rows;
154  }
155
156  /**
157   * Fills the missing weeks in the result.
158   */
159  protected static function weeks($result, $field) {
160    return self::date($result, $field, 52);
161  }
162
163  /**
164   * Fills the missing months in the result.
165   */
166  protected static function months($result, $field) {
167    return self::date($result, $field, 12);
168  }
169
170  /**
171   * Fills the missing days of week in the result.
172   */
173  protected static function daysOfWeek($result, $field) {
174    return self::integer($result, $field, 7);
175  }
176
177  /**
178   * Fills the missing days of month in the result.
179   */
180  protected static function dayOfMonth($result, $field) {
181    return self::integer($result, $field, 32, 1);
182  }
183
184  /**
185   * Fills the missing integer in the result.
186   */
187  protected static function integer($result, $field, $end, $start = 0) {
188
189    $exclude_fields = [
190      'index',
191      '_entity',
192      '_relationship_entities',
193      $field,
194    ];
195
196    $rows = [];
197    $expected = $start;
198    $index = 0;
199    $row = NULL;
200    foreach ($result as $i => $row) {
201      while ($expected < (int) $row->{$field}) {
202        $clone = clone $row;
203        $clone->{$field} = str_pad($expected, 2, '0', STR_PAD_LEFT);
204        $clone->index = $index;
205        foreach (get_object_vars($clone) as $key => $value) {
206          if (in_array($key, $exclude_fields)) {
207            continue;
208          }
209          $clone->{$key} = '0';
210        }
211
212        $rows[] = $clone;
213        $index += 1;
214        $expected += 1;
215      }
216      $row->index = $index;
217      $row->{$field} = str_pad($row->{$field} ?? '', 2, '0', STR_PAD_LEFT);
218      $rows[] = $row;
219      $index += 1;
220      $expected += 1;
221    }
222
223    while (!is_null($row) && $expected < $end) {
224      $clone = clone $row;
225      $clone->{$field} = str_pad($expected, 2, '0', STR_PAD_LEFT);
226      $clone->index = $index;
227      foreach (get_object_vars($clone) as $key => $value) {
228        if (in_array($key, $exclude_fields)) {
229          continue;
230        }
231        $clone->{$key} = '0';
232      }
233
234      $rows[] = $clone;
235      $index += 1;
236      $expected += 1;
237    }
238
239    return $rows;
240  }
241
242}