GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( de0e2b...79696a )
by Ronald
33:54 queued 21:00
created

AbstractCalendar::groupData()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
rs 9.0534
cc 4
eloc 14
nc 4
nop 2
1
<?php
2
3
/**
4
 * @file
5
 * Class AbstractCalendar
6
 */
7
8
namespace Roomify\Bat\Calendar;
9
10
use Roomify\Bat\Event\Event;
11
use Roomify\Bat\Calendar\CalendarInterface;
12
use Roomify\Bat\Calendar\CalendarResponse;
13
14
/**
15
 * Handles querying and updating state stores
16
 */
17
abstract class AbstractCalendar implements CalendarInterface {
18
19
  /**
20
   * The units we are dealing with. If no unit ids set the calendar will return
21
   * results for date range and all units within that range.
22
   *
23
   * @var array
24
   */
25
  public $units;
26
27
28
  /**
29
   * The class that will access the actual event store where event data is held.
30
   *
31
   * @var
32
   */
33
  public $store;
34
35
  /**
36
   * The default value for events. In the event store this is represented by 0 which is then
37
   * replaced by the default value provided in the constructor.
38
   *
39
   * @var
40
   */
41
  public $default_value;
42
43
44
  /**
45
   * {@inheritdoc}
46
   */
47
  public function addEvents($events, $granularity) {
48
49
    $added = TRUE;
50
51
    foreach ($events as $event) {
52
      // Events save themselves so here we cycle through each and return true if all events
53
      // were saved
54
55
      $check = $event->saveEvent($this->store, $granularity);
56
57
      if ($check == FALSE) {
58
        $added = FALSE;
59
        watchdog('BAT', t('Event with @id, start date @start_date and end date @end_date was not added.', array('@id' => $event->value, '@start_date' => $event->startDateToString(), '@end_date' => $event->endDateToString())));
60
        break;
61
      }
62
      else {
63
        watchdog('BAT', t('Event with @id, start date @start_date and end date @end_date added.', array('@id' => $event->value, '@start_date' => $event->startDateToString(), '@end_date' => $event->endDateToString())));
64
      }
65
    }
66
67
    return $added;
68
  }
69
70
  /**
71
   * Given a start and end time will retrieve events from the defined store.
72
   *
73
   * If unit_ids where defined it will filter for those unit ids.
74
   *
75
   * @param \DateTime $start_date
76
   * @param \DateTime $end_date
77
   * @return array
78
   */
79
  public function getEvents(\DateTime $start_date, \DateTime $end_date) {
80
    // We first get events in the itemized format
81
    $itemized_events = $this->getEventsItemized($start_date, $end_date);
82
83
    // We then normalize those events to create Events that get added to an array
84
    $events = $this->getEventsNormalized($start_date, $end_date, $itemized_events);
85
86
    return $events;
87
  }
88
89
  /**
90
   * Given a start and end time this will return the states units find themselves in for that range.
91
   *
92
   * @param \DateTime $start_date
93
   * @param \DateTime $end_date
94
   * @return array
95
   *  An array of states keyed by unit
96
   */
97
  public function getStates(\DateTime $start_date, \DateTime $end_date) {
98
    $events = $this->getEvents($start_date, $end_date);
99
    $states = array();
100
    foreach ($events as $unit => $unit_events) {
101
      foreach ($unit_events as $event) {
102
        $states[$unit][$event->getValue()] = $event->getValue();
103
      }
104
    }
105
106
    return $states;
107
  }
108
109
  /**
110
   * Given a date range and a set of valid states it will return then units that are withing that
111
   * set of valid states.
112
   *
113
   * @param \DateTime $start_date
114
   * @param \DateTime $end_date
115
   * @param $valid_states
116
   *
117
   * @return CalendarResponse
118
   */
119
  public function getMatchingUnits(\DateTime $start_date, \DateTime $end_date, $valid_states, $constraints) {
120
    $units = array();
121
    $response = new CalendarResponse($start_date, $end_date, $valid_states);
122
    $keyed_units = $this->keyUnitsById();
123
124
    $states = $this->getStates($start_date, $end_date);
125
    foreach ($states as $unit => $unit_states) {
126
      // Create an array with just the states
127
      $current_states = array_keys($unit_states);
128
      // Compare the current states with the set of valid states
129
      $remaining_states = array_diff($current_states, $valid_states);
130
      if (count($remaining_states) == 0 ) {
131
        // Unit is in a state that is within the set of valid states so add to result set
132
        $units[$unit] = $unit;
133
        $response->addMatch($keyed_units[$unit], CalendarResponse::VALID_STATE);
134
      }
135
      else {
136
        $response->addMiss($keyed_units[$unit], CalendarResponse::INVALID_STATE);
137
      }
138
139
      $unit_constraints = $keyed_units[$unit]->getConstraints();
140
      $response->applyConstraints($unit_constraints);
141
    }
142
143
    $response->applyConstraints($constraints);
144
145
    return $response;
146
  }
147
148
  /**
149
   * Provides an itemized array of events keyed by the unit_id and divided by day,
150
   * hour and minute.
151
   *
152
   * @param \DateTime $start_date
153
   * @param \DateTime $end_date
154
   * @param $store
155
   *
156
   * @return array
157
   */
158
  public function getEventsItemized(\DateTime $start_date, \DateTime $end_date) {
159
    // The final events we will return
160
    $events = array();
161
162
    $keyed_units = $this->keyUnitsById();
163
164
    $db_events = $this->store->getEventData($start_date, $end_date, array_keys($keyed_units));
165
166
    // Create a mock itemized event for the period in question - since event data is either
167
    // in the database or the default value we first create a mock event and then fill it in
168
    // accordingly
169
    $mock_event = new Event($start_date, $end_date, NULL, $this->default_value);
170
    $itemized = $mock_event->itemizeEvent();
171
172
    // Cycle through each unit retrieved and provide it with a fully configured itemized mock event
173
    foreach ($db_events as $unit => $event) {
174
      // Add the mock event
175
      $events[$unit] = $itemized;
176
177
      // Fill in month data coming from the database for our event
178
      foreach ($itemized[BAT_DAY] as $year => $months) {
179
        foreach ($months as $month => $days) {
180
          // Check if month is defined in DB otherwise set to default value
181
          if (isset($db_events[$unit][BAT_DAY][$year][$month])) {
182
            foreach ($days as $day => $value) {
183
              $events[$unit][BAT_DAY][$year][$month][$day] = ((int)$db_events[$unit][BAT_DAY][$year][$month][$day] == 0 ? $keyed_units[$unit]->getDefaultValue() : (int)$db_events[$unit][BAT_DAY][$year][$month][$day]);
184
            }
185
          }
186 View Code Duplication
          else {
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...
187
            foreach ($days as $day => $value) {
188
              $events[$unit][BAT_DAY][$year][$month][$day] = $keyed_units[$unit]->getDefaultValue();
189
            }
190
          }
191
192
        }
193
      }
194
195
      // Fill in hour data coming from the database for our event that is represented
196
      // in the mock event
197
      foreach ($itemized[BAT_HOUR] as $year => $months) {
198
        foreach ($months as $month => $days) {
199
          foreach ($days as $day => $hours) {
200
            foreach ($hours as $hour => $value) {
201
              if (isset($db_events[$unit][BAT_HOUR][$year][$month][$day][$hour])) {
202
                $events[$unit][BAT_HOUR][$year][$month]['d' . $day][$hour] = ((int)$db_events[$unit][BAT_DAY][$year][$month][$day][$hour] == 0 ? $keyed_units[$unit]->getDefaultValue() : (int)$db_events[$unit][BAT_DAY][$year][$month][$day][$hour]);
203
              }
204 View Code Duplication
              else {
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...
205
                // If nothing from db - then revert to the defaults
206
                $events[$unit][BAT_HOUR][$year][$month][$day][$hour] = (int)$keyed_units[$unit]->getDefaultValue();
207
              }
208
            }
209
          }
210
        }
211
      }
212
213
      // Now fill in hour data coming from the database which the mock event did *not* cater for
214
      // but the mock event
215 View Code Duplication
      foreach ($db_events[$unit][BAT_HOUR] as $year => $months) {
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...
216
        foreach ($months as $month => $days) {
217
          foreach ($days as $day => $hours) {
218
            foreach ($hours as $hour => $value) {
219
              $events[$unit][BAT_HOUR][$year][$month]['d'.$day][$hour] = ((int)$value == 0 ? $keyed_units[$unit]->getDefaultValue() : (int)$value);
220
            }
221
          }
222
        }
223
      }
224
225
      // Fill in minute data coming from the database for our event that is represented
226
      // in the mock event
227
      foreach ($itemized[BAT_MINUTE] as $year => $months) {
228
        foreach ($months as $month => $days) {
229
          foreach ($days as $day => $hours) {
230
            foreach ($hours as $hour => $minutes) {
231
              foreach ($minutes as $minute => $value) {
232
                if (isset($db_events[$unit][BAT_MINUTE][$year][$month][$day][$hour][$minute])) {
233
                  $events[$unit][BAT_MINUTE][$year][$month]['d' .$day]['h'.$hour][$minute] = ((int)$db_events[$unit][BAT_DAY][$year][$month][$day][$hour][$minute] == 0 ? $keyed_units[$unit]->getDefaultValue() : (int)$db_events[$unit][BAT_DAY][$year][$month][$day][$hour][$minute]);
234
                }
235 View Code Duplication
                else {
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...
236
                  // If nothing from db - then revert to the defaults
237
                  $events[$unit][BAT_MINUTE][$year][$month][$day][$hour][$minute] = (int)$keyed_units[$unit]->getDefaultValue();
238
                }
239
              }
240
            }
241
          }
242
        }
243
      }
244
245
      // Now fill in minute data coming from the database which the mock event did *not* cater for
246
      foreach ($db_events[$unit][BAT_MINUTE] as $year => $months) {
247 View Code Duplication
        foreach ($months as $month => $days) {
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...
248
          foreach ($days as $day => $hours) {
249
            foreach ($hours as $hour => $minutes) {
250
              foreach ($minutes as $minute => $value) {
251
                $events[$unit][BAT_MINUTE][$year][$month]['d'.$day]['h'.$hour][$minute] = ((int)$value == 0 ? $keyed_units[$unit]->getDefaultValue() : (int)$value);
252
              }
253
            }
254
          }
255
        }
256
      }
257
258
    }
259
260
    // Check to see if any events came back from the db
261
    if (count($events) == 0) {
262
      // If we don't have any db events add mock events (itemized)
263
      foreach ($keyed_units as $id => $unit) {
264
        $empty_event = new Event($start_date, $end_date, $id, $unit->getDefaultValue());
265
        $events[$id] = $empty_event->itemizeEvent();
266
      }
267
    }
268
269
    return $events;
270
  }
271
272
  /**
273
   * Given an itemized set of event data it will return an array of Events
274
   *
275
   * @param \DateTime $start_date
276
   * @param \DateTime $end_date
277
   * @param $events
278
   *
279
   * @return array
280
   */
281
  public function getEventsNormalized(\DateTime $start_date, \DateTime $end_date, $events) {
282
283
    $normalized_events = array();
284
285
    $events_copy = $events;
286
287
    foreach ($events_copy as $unit => $data) {
288
289
      // Make sure years are sorted
290
      ksort($data[Event::BAT_DAY]);
291
      ksort($data[Event::BAT_HOUR]);
292
      ksort($data[Event::BAT_MINUTE]);
293
294
      // Set up variables to keep track of stuff
295
      $current_value = NULL;
296
      $start_event = NULL;
297
      $end_event = NULL;
298
      $event_value = NULL;
0 ignored issues
show
Unused Code introduced by
$event_value is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
299
300
      foreach ($data[Event::BAT_DAY] as $year => $months) {
301
        // Make sure months are in right order
302
        ksort($months);
303
        foreach ($months as $month => $days) {
304
          foreach ($days as $day => $value) {
305
            if ($value == -1) {
306
              // Retrieve hour data
307
              $hour_data = $events[$unit][Event::BAT_HOUR][$year][$month][$day];
308
              ksort($hour_data, SORT_NATURAL);
309
              foreach ($hour_data as $hour => $hour_value) {
310
                if ($hour_value == -1) {
311
                  // We are going to need minute values
312
                  $minute_data = $events[$unit][Event::BAT_MINUTE][$year][$month][$day][$hour];
313
                  ksort($minute_data, SORT_NATURAL);
314
                  foreach ($minute_data as $minute => $minute_value) {
315
                    if ($current_value === $minute_value) {
316
                      // We are still in minutes and going through so add a minute
317
                      $end_event->add(new \DateInterval('PT1M'));
318
                    }
319
                    elseif (($current_value != $minute_value) && ($current_value !== NULL)) {
320
                      // Value just switched - let us wrap up with current event and start a new one
321
                      $normalized_events[$unit][] = new Event($start_event, $end_event, $unit, $current_value);
0 ignored issues
show
Documentation introduced by
$start_event is of type object|null, but the function expects a object<DateTime>.

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...
Bug introduced by
It seems like $end_event defined by NULL on line 297 can be null; however, Roomify\Bat\Event\Event::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
322
                      $start_event = clone($end_event->add(new \DateInterval('PT1M')));
323
                      $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':' . substr($minute,1));
324
                      $current_value = $minute_value;
325
                    }
326
                    if ($current_value === NULL) {
327
                      // We are down to minutes and haven't created and event yet - do one now
328
                      $start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':' . substr($minute,1));
329
                      $end_event = clone($start_event);
330
                    }
331
                    $current_value = $minute_value;
332
                  }
333
                }
334
                elseif ($current_value === $hour_value) {
335
                  // We are in hours and can add something
336
                  $end_event->add(new \DateInterval('PT1H'));
337
                }
338 View Code Duplication
                elseif (($current_value != $hour_value) && ($current_value !== NULL)) {
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...
339
                  // Value just switched - let us wrap up with current event and start a new one
340
                  $normalized_events[$unit][] = new Event($start_event, $end_event, $unit, $current_value);
0 ignored issues
show
Documentation introduced by
$start_event is of type object|null, but the function expects a object<DateTime>.

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...
Bug introduced by
It seems like $end_event defined by NULL on line 297 can be null; however, Roomify\Bat\Event\Event::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
341
                  // Start event becomes the end event with a minute added
342
                  $start_event = clone($end_event->add(new \DateInterval('PT1M')));
343
                  // End event comes the current point in time
344
                  $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':00');
345
                  $current_value = $hour_value;
346
                }
347
                if ($current_value === NULL) {
348
                  // Got into hours and still haven't created an event so
349
                  $start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':00');
350
                  // We will be occupying at least this hour so might as well mark it
351
                  $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . substr($hour, 1) . ':59');
352
                  $current_value = $hour_value;
353
                }
354
              }
355
            }
356
            elseif ($current_value === $value) {
357
              // We are adding a whole day so the end event gets moved to the end of the day we are adding
358
              $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
359
            }
360 View Code Duplication
            elseif (($current_value !== $value) && ($current_value !== NULL)) {
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...
361
              // Value just switched - let us wrap up with current event and start a new one
362
              $normalized_events[$unit][] = new Event($start_event, $end_event, $unit, $current_value);
0 ignored issues
show
Documentation introduced by
$start_event is of type object|null, but the function expects a object<DateTime>.

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...
Bug introduced by
It seems like $end_event defined by NULL on line 297 can be null; however, Roomify\Bat\Event\Event::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
363
              // Start event becomes the end event with a minute added
364
              $start_event = clone($end_event->add(new \DateInterval('PT1M')));
365
              // End event becomes the current day which we have not account for yet
366
              $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
367
              $current_value = $value;
368
            }
369
            if ($current_value === NULL) {
370
              // We have not created an event yet so let's do it now
371
              $start_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '00:00');
372
              $end_event = new \DateTime($year . '-' . $month . '-' . substr($day, 1) . ' ' . '23:59');
373
              $current_value = $value;
374
            }
375
          }
376
        }
377
      }
378
379
      // Add the last event in for which there is nothing in the loop to catch it
380
      $normalized_events[$unit][] = new Event($start_event, $end_event, $unit, $current_value);
0 ignored issues
show
Documentation introduced by
$start_event is of type object|null, but the function expects a object<DateTime>.

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...
Bug introduced by
It seems like $end_event defined by NULL on line 297 can be null; however, Roomify\Bat\Event\Event::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
381
    }
382
383
    // Given the database structure we may get events that are not with the date ranges we were looking for
384
    // We get rid of them here so that the user has a clean result.
385
    foreach ($normalized_events as $unit => $events) {
386
      foreach ($events as $key => $event) {
387
        if ($event->inRange($start_date, $end_date)) {
388
          // Adjust start or end dates of events so everything is within range
389
          if ($event->startsEarlier($start_date)) {
390
            $event->setStartDate($start_date);
391
          }
392
          if ($event->endsLater($end_date)) {
393
            $event->setEndDate($end_date);
394
          }
395
        }
396
        else {
397
          // Event completely not in range so unset it
398
          unset($normalized_events[$unit][$key]);
399
        }
400
      }
401
    }
402
403
    return $normalized_events;
404
  }
405
406
  /**
407
   * A simple utility function that given an array of datum=>value will group results based on
408
   * those that have the same value. Useful for grouping events based on state.
409
   *
410
   * @param $data
411
   * @param $length
412
   */
413
  public function groupData($data, $length) {
414
    $flipped = array();
415
    $e = 0;
416
    $j = 0;
417
    $old_value = NULL;
418
419
    foreach ($data as $datum => $value) {
420
      $j++;
421
      if ($j <= $length) {
422
        // If the value has changed and we are not just starting
423
        if (($value != $old_value)) {
424
          $e++;
425
          $flipped[$e][$value][$datum] = $datum;
426
          $old_value = $value;
427
        }
428
        else {
429
          $flipped[$e][$value][$datum] = $datum;
430
        }
431
      }
432
    }
433
  }
434
435
  /**
436
   * Return an array of unit ids from the set of units
437
   * supplied to the Calendar.
438
   *
439
   * @return array
440
   */
441
  public function getUnitIds() {
442
    $unit_ids = array();
443
    foreach ($this->units as $unit) {
444
      $unit_ids[] = $unit->getUnitId();
445
    }
446
447
    return $unit_ids;
448
  }
449
450
  /**
451
   * Return an array of units keyed by unit id
452
   *
453
   * @return array
454
   */
455
  public function keyUnitsById() {
456
    $keyed_units = array();
457
    foreach ($this->units as $unit) {
458
      $keyed_units[$unit->getUnitId()] = $unit;
459
    }
460
461
    return $keyed_units;
462
  }
463
464
}
465