TimeLine.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. namespace App\Helpers;
  3. use DateTime;
  4. class TimeLine {
  5. public $start = null;
  6. public $end = null;
  7. public $available = [];
  8. public $unavailable = [];
  9. public $removeStart = null;
  10. public $removeEnd = null;
  11. public function __construct(DateTime $_start, DateTime $_end)
  12. {
  13. $this->start = $_start->getTimestamp();
  14. $this->end = $_end->getTimestamp();
  15. }
  16. public function addAvailability(DateTime $_start, DateTime $_end) {
  17. $this->available[] = new TimeSlot($_start, $_end);
  18. // sort by start
  19. usort($this->available, function ($item1, $item2) {
  20. return $item1->start <=> $item2->start;
  21. });
  22. // compact (join adjacent overlapping slots)
  23. // $this->vdump($this->available);
  24. $this->normalize();
  25. $this->vdump($this->available);
  26. }
  27. public function removeAvailability(DateTime $_start, DateTime $_end) {
  28. $this->removeStart = $_start->getTimestamp();
  29. $this->removeEnd = $_end->getTimestamp();
  30. $this->cleanRemove();
  31. $removeStart = null;
  32. $removeSnd = null;
  33. // sort by start
  34. usort($this->available, function ($item1, $item2) {
  35. return $item1->start <=> $item2->start;
  36. });
  37. $this->normalize();
  38. $this->vdump($this->available);
  39. }
  40. private function cleanRemove() {
  41. $allDone = true;
  42. for ($i=0; $i<count($this->available); $i++) {
  43. // removeStart at or after slot start
  44. // removeEnd at or before slot end
  45. // split slot into 2
  46. if($this->removeStart >= $this->available[$i]->start &&
  47. $this->removeEnd <= $this->available[$i]->end) {
  48. $newSlot = new TimeSlot(new DateTime(), new DateTime());
  49. $newSlot->start = $this->removeEnd;
  50. $newSlot->end = $this->available[$i]->end;
  51. $this->available[$i]->end = $this->removeStart;
  52. array_splice($this->available, $i+1, 0, [$newSlot]);
  53. $allDone = true;
  54. break;
  55. }
  56. // removeStart at or after slot start
  57. // removeStart at or before slot end
  58. // update slot to end at removeStart
  59. if($this->removeStart >= $this->available[$i]->start &&
  60. $this->removeStart <= $this->available[$i]->end) {
  61. $this->available[$i]->end = $this->removeStart;
  62. $allDone = false;
  63. break;
  64. }
  65. // process removeEnd
  66. // removeEnd at or after slot start
  67. // removeEnd at or before slot end
  68. // update slot to start at removeEnd
  69. if($this->removeEnd >= $this->available[$i]->start &&
  70. $this->removeEnd <= $this->available[$i]->end) {
  71. $this->available[$i]->start = $this->removeEnd;
  72. $allDone = false;
  73. break;
  74. }
  75. }
  76. if(!$allDone) {
  77. $this->normalize(); // recurse till clean
  78. }
  79. }
  80. private function normalize() {
  81. $allDone = true;
  82. for ($i=0; $i<count($this->available)-1; $i++) {
  83. if($this->available[$i]->end >= $this->available[$i+1]->start && // ends in the middle of next slot
  84. $this->available[$i]->end <= $this->available[$i+1]->end)
  85. {
  86. // extend self & delete next
  87. $this->available[$i]->end = $this->available[$i+1]->end;
  88. array_splice($this->available, $i+1, 1);
  89. $allDone = false;
  90. break;
  91. }
  92. if($this->available[$i]->end >= $this->available[$i+1]->end) // ends after next slot end
  93. {
  94. // delete next
  95. array_splice($this->available, $i+1, 1);
  96. $allDone = false;
  97. break;
  98. }
  99. if($this->available[$i]->start >= $this->available[$i]->end) // starts and ends at the same time!
  100. {
  101. // delete self
  102. array_splice($this->available, $i, 1);
  103. $allDone = false;
  104. break;
  105. }
  106. }
  107. if(!$allDone) {
  108. $this->normalize(); // recurse till clean
  109. }
  110. }
  111. public function vdump($_x) {
  112. // echo "<pre>";
  113. // print_r($_x);
  114. // echo "</pre><hr>";
  115. }
  116. }