| 1 | <?php |
||
| 2 | |||
| 3 | namespace Vctls\IntervalGraph; |
||
| 4 | |||
| 5 | /** |
||
| 6 | * A class to manipulate and display arrays of weighted intervals. |
||
| 7 | */ |
||
| 8 | class IntervalGraph implements \JsonSerializable |
||
| 9 | { |
||
| 10 | /** @var array Initial intervals */ |
||
| 11 | protected $intervals; |
||
| 12 | |||
| 13 | /** @var array Processed values */ |
||
| 14 | protected $values; |
||
| 15 | |||
| 16 | /** @var string Path to the template used for rendering. */ |
||
| 17 | protected $template = 'template.php'; |
||
| 18 | |||
| 19 | /** @var \Closure Return a numeric value from the inital bound value. */ |
||
| 20 | protected $boundToNumeric; |
||
| 21 | |||
| 22 | /** @var \Closure Return a string from the initial bound value. */ |
||
| 23 | protected $boundToString; |
||
| 24 | |||
| 25 | /** @var \Closure Return a numeric value from an initial interval value. */ |
||
| 26 | protected $valueToNumeric; |
||
| 27 | |||
| 28 | /** @var \Closure Return a string value from an initial interval value. */ |
||
| 29 | protected $valueToString; |
||
| 30 | |||
| 31 | /** @var \Closure Aggregate interval values. */ |
||
| 32 | protected $aggregateFunction; |
||
| 33 | |||
| 34 | /** @var Palette */ |
||
| 35 | protected $palette; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Create an IntervalGraph from intervals carrying values. |
||
| 39 | * |
||
| 40 | * @param array[] $intervals An array of intervals, |
||
| 41 | * with a low bound, high bound and a value. |
||
| 42 | */ |
||
| 43 | public function __construct($intervals = null) |
||
| 44 | { |
||
| 45 | if (isset($intervals)) { |
||
| 46 | $this->setIntervals($intervals); |
||
| 47 | } |
||
| 48 | |||
| 49 | $this->boundToNumeric = function (\DateTime $bound) { |
||
| 50 | return $bound->getTimestamp(); |
||
| 51 | }; |
||
| 52 | |||
| 53 | $this->boundToString = function (\DateTime $bound) { |
||
| 54 | return $bound->format("Y-m-d"); |
||
| 55 | }; |
||
| 56 | |||
| 57 | $this->valueToNumeric = function ($v) { |
||
| 58 | return $v === null ? null : (int)($v * 100); |
||
| 59 | }; |
||
| 60 | |||
| 61 | $this->valueToString = function ($v) { |
||
| 62 | return $v === null ? null : ($v * 100 . '%'); |
||
| 63 | }; |
||
| 64 | |||
| 65 | $this->aggregateFunction = function ($a, $b) { |
||
| 66 | if ($a === null && $b === null) { |
||
| 67 | return null; |
||
| 68 | } |
||
| 69 | return round($a + $b, 2); |
||
| 70 | }; |
||
| 71 | |||
| 72 | $this->palette = new Palette(); |
||
| 73 | } |
||
| 74 | |||
| 75 | /** |
||
| 76 | * Check that an array of intervals is correctly formatted. |
||
| 77 | * |
||
| 78 | * The first element must be the low bound. |
||
| 79 | * |
||
| 80 | * The second element must be the high bound. |
||
| 81 | * |
||
| 82 | * The third element must be the value. |
||
| 83 | * |
||
| 84 | * Inverted end and low bounds will be put back in chronological order. |
||
| 85 | * |
||
| 86 | * @return $this |
||
| 87 | */ |
||
| 88 | public function checkIntervals() |
||
| 89 | { |
||
| 90 | |||
| 91 | if (!isset($intervals)) { |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
| 92 | $intervals = $this->intervals; |
||
| 93 | } |
||
| 94 | |||
| 95 | foreach ($intervals as $intervalKey => $interval) { |
||
| 96 | |||
| 97 | // Check that the interval is an array. |
||
| 98 | if (!is_array($interval)) { |
||
| 99 | $t = gettype($interval); |
||
| 100 | throw new \InvalidArgumentException( |
||
| 101 | "Each element of the '\$intervals' array should be an array, $t given." |
||
| 102 | ); |
||
| 103 | } |
||
| 104 | |||
| 105 | // Check that the bounds and value of the interval can be converted to both a numeric |
||
| 106 | // and string value with the given closures. |
||
| 107 | foreach ([['Lower bound', 'bound'], ['Higher bound', 'bound'], ['Value', 'value']] as $index => $property) { |
||
| 108 | |||
| 109 | // Skip value property of valueless intervals. |
||
| 110 | if ($property[1] === 'value' && !isset($interval[$index])) { |
||
| 111 | continue; |
||
| 112 | } |
||
| 113 | |||
| 114 | foreach (['numeric', 'string'] as $expectedType) { |
||
| 115 | |||
| 116 | $expectedTypeTitle = ucfirst($expectedType); |
||
| 117 | |||
| 118 | try { |
||
| 119 | $value = ($this->{"$property[1]To$expectedTypeTitle"})($interval[$index]); |
||
| 120 | } catch (\Exception $exception) { |
||
| 121 | throw new \InvalidArgumentException( |
||
| 122 | "$property[0] of interval $intervalKey cannot be converted to a $expectedType value " . |
||
| 123 | "with the given '$property[1]To$expectedTypeTitle' function. Error : " . $exception->getMessage() |
||
| 124 | ); |
||
| 125 | } |
||
| 126 | |||
| 127 | $actualType = gettype($value); |
||
| 128 | |||
| 129 | if (!call_user_func("is_$expectedType", $value)) { |
||
| 130 | throw new \InvalidArgumentException( |
||
| 131 | "$property[0] of interval $intervalKey is not converted to a $expectedType value " . |
||
| 132 | "by the given '$property[1]To$expectedTypeTitle' function. Returned type : $actualType" |
||
| 133 | ); |
||
| 134 | } |
||
| 135 | } |
||
| 136 | } |
||
| 137 | |||
| 138 | // Ensure start and high bounds are in the right order. |
||
| 139 | if ($interval[0] > $interval [1]) { |
||
| 140 | $a = $interval[0]; |
||
| 141 | $intervals[$intervalKey][0] = $interval[1]; |
||
| 142 | $intervals[$intervalKey][1] = $a; |
||
| 143 | } |
||
| 144 | } |
||
| 145 | |||
| 146 | // TODO Check that the values can be aggregated with the given closure. |
||
| 147 | |||
| 148 | return $this; |
||
| 149 | } |
||
| 150 | |||
| 151 | /** |
||
| 152 | * Truncate all intervals to the given lower and upper limits. |
||
| 153 | * |
||
| 154 | * @param array $intervals |
||
| 155 | * @param mixed $lowerLimit |
||
| 156 | * @param mixed $upperLimit |
||
| 157 | * @param bool $padding Add null value intervals between the bounds and the first and last bounds. |
||
| 158 | * @return array |
||
| 159 | */ |
||
| 160 | public static function truncate(array $intervals, $lowerLimit = null, $upperLimit = null, $padding = false) |
||
| 161 | { |
||
| 162 | if (isset($lowerLimit)) { |
||
| 163 | $intervals = array_map(function ($i) use ($lowerLimit) { |
||
| 164 | if ($i[0] < $lowerLimit) { // If the low bound is before the lower bound... |
||
| 165 | if ($i[1] < $lowerLimit) { |
||
| 166 | // ... and the high bound is also before the lower bound, set the interval to false. |
||
| 167 | $i = false; |
||
| 168 | } else { |
||
| 169 | // If only the low bound is before the lower bound, set it to the bound value. |
||
| 170 | $i[0] = $lowerLimit; |
||
| 171 | } |
||
| 172 | } |
||
| 173 | return $i; |
||
| 174 | }, $intervals); |
||
| 175 | |||
| 176 | // Remove false elements. |
||
| 177 | $intervals = array_filter($intervals); |
||
| 178 | |||
| 179 | // If padding is required and a lower limit is set and is inferior to the min bound, |
||
| 180 | // add a weightless interval between that bound and the limit. |
||
| 181 | if ($padding) { |
||
| 182 | $minBound = self::minBound($intervals); |
||
| 183 | if (isset($minBound) && $minBound > $lowerLimit) { |
||
| 184 | $intervals[] = [$lowerLimit, $minBound]; |
||
| 185 | } |
||
| 186 | } |
||
| 187 | } |
||
| 188 | |||
| 189 | // TODO DRY |
||
| 190 | if (isset($upperLimit)) { |
||
| 191 | $intervals = array_map(function ($i) use ($upperLimit) { |
||
| 192 | if ($i[1] > $upperLimit) { |
||
| 193 | if ($i[0] > $upperLimit) { |
||
| 194 | // If both bounds are after the given upper limit, set the interval to false. |
||
| 195 | $i = false; |
||
| 196 | } else { |
||
| 197 | // If only the high bound is after the upper limit, set it to the bound value. |
||
| 198 | $i[1] = $upperLimit; |
||
| 199 | } |
||
| 200 | } |
||
| 201 | return $i; |
||
| 202 | }, $intervals); |
||
| 203 | |||
| 204 | // Remove false elements. |
||
| 205 | $intervals = array_filter($intervals); |
||
| 206 | |||
| 207 | // If padding is required and a upper limit is set and is superior to the max bound, |
||
| 208 | // add a valueless interval between that bound and the limit. |
||
| 209 | if ($padding) { |
||
| 210 | $maxBound = self::maxBound($intervals); |
||
| 211 | if (isset($maxBound) && $maxBound < $upperLimit) { |
||
| 212 | $intervals[] = [$upperLimit, $maxBound]; |
||
| 213 | } |
||
| 214 | } |
||
| 215 | } |
||
| 216 | |||
| 217 | return $intervals; |
||
| 218 | } |
||
| 219 | |||
| 220 | /** |
||
| 221 | * Get the minimum bound in an array of intervals. |
||
| 222 | * |
||
| 223 | * @param $intervals |
||
| 224 | * @return mixed |
||
| 225 | */ |
||
| 226 | public static function minBound($intervals) |
||
| 227 | { |
||
| 228 | $bounds = array_column($intervals, 0); |
||
| 229 | sort($bounds); |
||
| 230 | return array_shift($bounds); |
||
| 231 | } |
||
| 232 | |||
| 233 | /** |
||
| 234 | * Get the maximum bound in an array of intervals. |
||
| 235 | * |
||
| 236 | * @param $intervals |
||
| 237 | * @return mixed |
||
| 238 | */ |
||
| 239 | public static function maxBound($intervals) |
||
| 240 | { |
||
| 241 | $bounds = array_column($intervals, 1); |
||
| 242 | sort($bounds); |
||
| 243 | return array_pop($bounds); |
||
| 244 | } |
||
| 245 | |||
| 246 | /** |
||
| 247 | * Render an HTML view of the intervalGraph. |
||
| 248 | * |
||
| 249 | * @return string |
||
| 250 | */ |
||
| 251 | public function __toString() |
||
| 252 | { |
||
| 253 | try { |
||
| 254 | $html = $this->draw(); |
||
| 255 | } catch (\Exception $e) { |
||
| 256 | $html = "Error : " . $e->getMessage(); |
||
| 257 | } |
||
| 258 | return $html; |
||
| 259 | } |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Render an HTML view of the intervalGraph. |
||
| 263 | * |
||
| 264 | * @return string |
||
| 265 | */ |
||
| 266 | public function draw() |
||
| 267 | { |
||
| 268 | if (!isset($this->values)) { |
||
| 269 | $this->process(); |
||
| 270 | } |
||
| 271 | $vs = $this->values; |
||
| 272 | ob_start(); |
||
| 273 | include $this->template; |
||
| 274 | $html = ob_get_clean(); |
||
| 275 | // Remove all surplus whitespace. |
||
| 276 | $html = preg_replace(['/(?<=>)\s+/', '/\s+(?=<)/', '/\s+/'], ['', '', ' '], $html); |
||
| 277 | return $html; |
||
| 278 | } |
||
| 279 | |||
| 280 | /** |
||
| 281 | * Process intervals and store processed values. |
||
| 282 | * |
||
| 283 | * @return IntervalGraph |
||
| 284 | */ |
||
| 285 | public function process() |
||
| 286 | { |
||
| 287 | $flatIntervals = $this->getFlatIntervals(); |
||
| 288 | |||
| 289 | // Extract values. |
||
| 290 | $t = array_column($flatIntervals, 2); |
||
| 291 | |||
| 292 | // Change bounds to numeric values. |
||
| 293 | $numVals = array_map(function (array $i) { |
||
| 294 | return [ |
||
| 295 | ($this->boundToNumeric)($i[0]), |
||
| 296 | ($this->boundToNumeric)($i[1]), |
||
| 297 | ]; |
||
| 298 | }, $flatIntervals); |
||
| 299 | |||
| 300 | // Order by low bound. |
||
| 301 | uasort($numVals, function (array $i1, array $i2) { |
||
| 302 | return ($i1[0] < $i2[0]) ? -1 : 1; |
||
| 303 | }); |
||
| 304 | |||
| 305 | // Get the min timestamp. |
||
| 306 | $min = reset($numVals)[0]; |
||
| 307 | |||
| 308 | // Substract min from all timestamps. |
||
| 309 | $numVals = array_map(function ($i) use ($min) { |
||
| 310 | return [ |
||
| 311 | $i[0] - $min, |
||
| 312 | $i[1] - $min |
||
| 313 | ]; |
||
| 314 | }, $numVals); |
||
| 315 | |||
| 316 | // Order by high bound. |
||
| 317 | uasort($numVals, function (array $i1, array $i2) { |
||
| 318 | return ($i1[1] < $i2[1]) ? -1 : 1; |
||
| 319 | }); |
||
| 320 | |||
| 321 | // Get max timestamp. |
||
| 322 | $max = end($numVals)[1]; |
||
| 323 | |||
| 324 | // Calculate percentages. |
||
| 325 | $numVals = array_map(function (array $i) use ($max) { |
||
| 326 | return array_map(function ($int) use ($max) { |
||
| 327 | return round($int * 100 / $max); |
||
| 328 | }, $i); |
||
| 329 | }, $numVals); |
||
| 330 | |||
| 331 | // Put values back in, along with the formatted bound. |
||
| 332 | // Since we're using associative sorting functions, we know the keys haven't changed. |
||
| 333 | $numVals = array_map(function ($k, array $i) use ($t, $flatIntervals) { |
||
| 334 | if ($flatIntervals[$k][0] === $flatIntervals[$k][1]) { |
||
| 335 | return [ |
||
| 336 | $i[0], // Single value position percentage |
||
| 337 | ($this->boundToString)($flatIntervals[$k][0]), // Signle value string |
||
| 338 | ]; |
||
| 339 | } else { |
||
| 340 | $colorval = isset($t[$k]) ? ($this->valueToNumeric)($t[$k]) : null; |
||
| 341 | $stingval = isset($t[$k]) ? ($this->valueToString)($t[$k]) : null; |
||
| 342 | return [ |
||
| 343 | $i[0], // Interval start percentage |
||
| 344 | 100 - $i[1], // Interval end percentage from right |
||
| 345 | // Note: for some reason, using 'widht' instead of 'right' |
||
| 346 | // causes the right border to be hidden underneath the next interval. |
||
| 347 | !empty($t) ? $this->palette->getColor($colorval) : 50, // Interval color |
||
| 348 | ($this->boundToString)($flatIntervals[$k][0]), // Interval start string value |
||
| 349 | ($this->boundToString)($flatIntervals[$k][1]), // Interval end string value |
||
| 350 | !empty($t) ? ($stingval) : null,// Interval string value |
||
| 351 | ]; |
||
| 352 | } |
||
| 353 | }, array_keys($numVals), $numVals); |
||
| 354 | |||
| 355 | // Put discrete values at the end and reset indices. |
||
| 356 | // Reseting indices ensures the processed values are |
||
| 357 | // serialized as correctly ordered JSON arrays. |
||
| 358 | usort($numVals, function ($i) { |
||
| 359 | return count($i) === 2 ? 1 : -1; |
||
| 360 | }); |
||
| 361 | |||
| 362 | $this->values = $numVals; |
||
| 363 | |||
| 364 | return $this; |
||
| 365 | } |
||
| 366 | |||
| 367 | /** |
||
| 368 | * Transform an array of intervals with possible overlapping |
||
| 369 | * into an array of adjacent intervals with no overlapping. |
||
| 370 | * |
||
| 371 | * @return array |
||
| 372 | */ |
||
| 373 | public function getFlatIntervals() |
||
| 374 | { |
||
| 375 | $discreteValues = self::extractDiscreteValues($this->intervals); |
||
| 376 | $signedBounds = self::intervalsToSignedBounds($this->intervals); |
||
| 377 | $adjacentIntervals = $this->calcAdjacentIntervals($signedBounds); |
||
| 378 | |||
| 379 | // Remove empty interval generated when two or more intervals share a common bound. |
||
| 380 | $adjacentIntervals = array_values(array_filter($adjacentIntervals, function ($i) { |
||
| 381 | // Use weak comparison in case of object typed bounds. |
||
| 382 | return $i[0] != $i[1]; |
||
| 383 | })); |
||
| 384 | |||
| 385 | // Push discrete values back into the array. |
||
| 386 | if (!empty($discreteValues)) { |
||
| 387 | array_push($adjacentIntervals, ...$discreteValues); |
||
| 388 | } |
||
| 389 | |||
| 390 | return $adjacentIntervals; |
||
| 391 | } |
||
| 392 | |||
| 393 | /** |
||
| 394 | * Extract discrete values from an array of intervals. |
||
| 395 | * |
||
| 396 | * Intervals with the exact same lower and higher bound will be considered as discrete values. |
||
| 397 | * |
||
| 398 | * They will be removed from the initial array, and returned in a separate array. |
||
| 399 | * |
||
| 400 | * @param array $intervals The initial array. |
||
| 401 | * @return array An array containing only discrete values. |
||
| 402 | */ |
||
| 403 | public static function extractDiscreteValues(array &$intervals) |
||
| 404 | { |
||
| 405 | $discreteValues = array_filter($intervals, function ($interval) { |
||
| 406 | return $interval[0] === $interval[1]; |
||
| 407 | }); |
||
| 408 | |||
| 409 | $intervals = array_diff_key($intervals, $discreteValues); |
||
| 410 | |||
| 411 | return $discreteValues; |
||
| 412 | } |
||
| 413 | |||
| 414 | /** |
||
| 415 | * Make an array of bounds from an array of intervals. |
||
| 416 | * |
||
| 417 | * Assign the value of the interval to each bound. |
||
| 418 | * |
||
| 419 | * Assign and a '+' sign if it is a low bound, and a '-' if it is an high bound. |
||
| 420 | * |
||
| 421 | * @param $intervals |
||
| 422 | * @return array |
||
| 423 | */ |
||
| 424 | public static function intervalsToSignedBounds($intervals) |
||
| 425 | { |
||
| 426 | $bounds = []; |
||
| 427 | foreach ($intervals as $key => $interval) { |
||
| 428 | $bounds[] = [$interval[0], isset($interval[2]) ? $interval[2] : null, '+', $key]; |
||
| 429 | $bounds[] = [$interval[1], isset($interval[2]) ? $interval[2] : null, '-', $key]; |
||
| 430 | } |
||
| 431 | // Order the bounds. |
||
| 432 | usort($bounds, function (array $d1, array $d2) { |
||
| 433 | return ($d1[0] < $d2[0]) ? -1 : 1; |
||
| 434 | }); |
||
| 435 | return $bounds; |
||
| 436 | } |
||
| 437 | |||
| 438 | /** |
||
| 439 | * Create each new interval and calculate its value based on the active intervals on each bound. |
||
| 440 | * |
||
| 441 | * @param $bounds |
||
| 442 | * @return array |
||
| 443 | */ |
||
| 444 | public function calcAdjacentIntervals($bounds) |
||
| 445 | { |
||
| 446 | // Get the values of the original intervals, including nulls. |
||
| 447 | $origIntVals = array_map(function ($interval) { |
||
| 448 | return isset($interval[2]) ? $interval[2] : null; |
||
| 449 | }, $this->intervals); |
||
| 450 | |||
| 451 | $newIntervals = []; |
||
| 452 | $activeIntervals = []; |
||
| 453 | |||
| 454 | // Create new intervals for each set of two consecutive bounds, |
||
| 455 | // and calculate its total value. |
||
| 456 | for ($i = 1; $i < count($bounds); $i++) { |
||
|
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
|
|||
| 457 | |||
| 458 | // Set the current bound. |
||
| 459 | $curBound = $bounds[$i - 1]; |
||
| 460 | |||
| 461 | if ($curBound[2] === '+') { |
||
| 462 | // If this is a low bound, |
||
| 463 | // add the key of the interval to the array of active intervals. |
||
| 464 | $activeIntervals[$curBound[3]] = true; |
||
| 465 | } else { |
||
| 466 | // If this is an high bound, remove the key. |
||
| 467 | unset($activeIntervals[$curBound[3]]); |
||
| 468 | } |
||
| 469 | |||
| 470 | if (empty($activeIntervals)) { |
||
| 471 | // If no intervals are active on this bound, |
||
| 472 | // the value of this interval is null. |
||
| 473 | $ival = null; |
||
| 474 | } else { |
||
| 475 | // Else, aggregate the values of the corresponding intervals. |
||
| 476 | $ival = array_reduce( |
||
| 477 | array_intersect_key($origIntVals, $activeIntervals), |
||
| 478 | $this->aggregateFunction |
||
| 479 | ); |
||
| 480 | } |
||
| 481 | |||
| 482 | $newIntervals[] = [$curBound[0], $bounds[$i][0], $ival]; |
||
| 483 | } |
||
| 484 | |||
| 485 | return $newIntervals; |
||
| 486 | } |
||
| 487 | |||
| 488 | /** |
||
| 489 | * Define the function to convert the interval values to a numeric value |
||
| 490 | * in order to match them to a color on the palette. |
||
| 491 | * |
||
| 492 | * @param \Closure $valueToNumeric |
||
| 493 | * @return IntervalGraph |
||
| 494 | */ |
||
| 495 | public function setValueToNumeric(\Closure $valueToNumeric) |
||
| 496 | { |
||
| 497 | $this->valueToNumeric = $valueToNumeric; |
||
| 498 | return $this; |
||
| 499 | } |
||
| 500 | |||
| 501 | /** |
||
| 502 | * Define the function to convert the interval values to strings |
||
| 503 | * in order to display them in the view. |
||
| 504 | * |
||
| 505 | * @param \Closure $valueToString |
||
| 506 | * @return IntervalGraph |
||
| 507 | */ |
||
| 508 | public function setValueToString(\Closure $valueToString) |
||
| 509 | { |
||
| 510 | $this->valueToString = $valueToString; |
||
| 511 | return $this; |
||
| 512 | } |
||
| 513 | |||
| 514 | /** |
||
| 515 | * Define the function to aggregate interval values. |
||
| 516 | * |
||
| 517 | * @param \Closure $aggregate |
||
| 518 | * @return IntervalGraph |
||
| 519 | */ |
||
| 520 | public function setAggregate(\Closure $aggregate) |
||
| 521 | { |
||
| 522 | $this->aggregateFunction = $aggregate; |
||
| 523 | return $this; |
||
| 524 | } |
||
| 525 | |||
| 526 | /** |
||
| 527 | * Set the function to convert interval bound values to string. |
||
| 528 | * |
||
| 529 | * @param \Closure $boundToString |
||
| 530 | * @return IntervalGraph |
||
| 531 | */ |
||
| 532 | public function setBoundToString($boundToString) |
||
| 533 | { |
||
| 534 | $this->boundToString = $boundToString; |
||
| 535 | return $this; |
||
| 536 | } |
||
| 537 | |||
| 538 | /** |
||
| 539 | * @return array |
||
| 540 | */ |
||
| 541 | public function getIntervals() |
||
| 542 | { |
||
| 543 | return $this->intervals; |
||
| 544 | } |
||
| 545 | |||
| 546 | /** |
||
| 547 | * Set the intervals to be processed. |
||
| 548 | * |
||
| 549 | * If another set of intervals was previously processed, |
||
| 550 | * the processed values will be deleted. |
||
| 551 | * |
||
| 552 | * @param array $intervals |
||
| 553 | * @return IntervalGraph |
||
| 554 | */ |
||
| 555 | public function setIntervals(array $intervals) |
||
| 556 | { |
||
| 557 | $this->intervals = $intervals; |
||
| 558 | $this->values = null; |
||
| 559 | return $this; |
||
| 560 | } |
||
| 561 | |||
| 562 | /** |
||
| 563 | * @return array |
||
| 564 | */ |
||
| 565 | public function getValues() |
||
| 566 | { |
||
| 567 | return $this->values; |
||
| 568 | } |
||
| 569 | |||
| 570 | /** |
||
| 571 | * @return string |
||
| 572 | */ |
||
| 573 | public function getTemplate() |
||
| 574 | { |
||
| 575 | return $this->template; |
||
| 576 | } |
||
| 577 | |||
| 578 | /** |
||
| 579 | * Set the PHP template to use for rendering. |
||
| 580 | * |
||
| 581 | * @param string $template |
||
| 582 | * @return IntervalGraph |
||
| 583 | */ |
||
| 584 | public function setTemplate($template) |
||
| 585 | { |
||
| 586 | $this->template = $template; |
||
| 587 | return $this; |
||
| 588 | } |
||
| 589 | |||
| 590 | /** |
||
| 591 | * @return Palette |
||
| 592 | */ |
||
| 593 | public function getPalette() |
||
| 594 | { |
||
| 595 | return $this->palette; |
||
| 596 | } |
||
| 597 | |||
| 598 | /** |
||
| 599 | * @param Palette $palette |
||
| 600 | * @return IntervalGraph |
||
| 601 | */ |
||
| 602 | public function setPalette($palette) |
||
| 603 | { |
||
| 604 | $this->palette = $palette; |
||
| 605 | return $this; |
||
| 606 | } |
||
| 607 | |||
| 608 | /** |
||
| 609 | * @param \Closure $boundToNumeric |
||
| 610 | * @return IntervalGraph |
||
| 611 | */ |
||
| 612 | public function setBoundToNumeric($boundToNumeric) |
||
| 613 | { |
||
| 614 | $this->boundToNumeric = $boundToNumeric; |
||
| 615 | return $this; |
||
| 616 | } |
||
| 617 | |||
| 618 | /** |
||
| 619 | * Return the array of values to be serialized by json_encode. |
||
| 620 | * |
||
| 621 | * @return array |
||
| 622 | */ |
||
| 623 | public function jsonSerialize() |
||
| 624 | { |
||
| 625 | if (!isset($this->values)) { |
||
| 626 | $this->process(); |
||
| 627 | } |
||
| 628 | return $this->values; |
||
| 629 | } |
||
| 630 | } |