| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Calculator.php | 
					
						
							| 
									
										
										
										
											2023-07-04 06:23:59 -03:00
										 |  |  |  * Copyright (c) 2023 Antonio Spinelli https://github.com/tonicospinelli | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This file is part of Firefly III (https://github.com/firefly-iii). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU Affero General Public License as | 
					
						
							|  |  |  |  * published by the Free Software Foundation, either version 3 of the | 
					
						
							|  |  |  |  * License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU Affero General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU Affero General Public License | 
					
						
							|  |  |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  | declare(strict_types=1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  | namespace FireflyIII\Support\Calendar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use Carbon\Carbon; | 
					
						
							| 
									
										
										
										
											2023-10-29 17:41:14 +01:00
										 |  |  | use FireflyIII\Exceptions\IntervalException; | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Class Calculator | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  | class Calculator | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-12-22 20:37:54 +01:00
										 |  |  |     public const int DEFAULT_INTERVAL              = 1; | 
					
						
							|  |  |  |     private static ?\SplObjectStorage $intervalMap = null; | 
					
						
							|  |  |  |     private static array             $intervals    = []; | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |      * @throws IntervalException | 
					
						
							| 
									
										
										
										
											2023-07-04 13:29:19 +02:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     public function nextDateByInterval(Carbon $epoch, Periodicity $periodicity, int $skipInterval = 0): Carbon | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         if (!self::isAvailablePeriodicity($periodicity)) { | 
					
						
							|  |  |  |             throw IntervalException::unavailable($periodicity, self::$intervals); | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /** @var Periodicity\Interval $periodicity */ | 
					
						
							|  |  |  |         $periodicity = self::$intervalMap->offsetGet($periodicity); | 
					
						
							|  |  |  |         $interval    = $this->skipInterval($skipInterval); | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         return $periodicity->nextDate($epoch->clone(), $interval); | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     public function isAvailablePeriodicity(Periodicity $periodicity): bool | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         return self::containsInterval($periodicity); | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     private static function containsInterval(Periodicity $periodicity): bool | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         return self::loadIntervalMap()->contains($periodicity); | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-12-21 06:06:23 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @SuppressWarnings(PHPMD.MissingImport) | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-12-22 20:37:54 +01:00
										 |  |  |     private static function loadIntervalMap(): \SplObjectStorage | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  |         if (null !== self::$intervalMap) { | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |             return self::$intervalMap; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-12-22 20:37:54 +01:00
										 |  |  |         self::$intervalMap = new \SplObjectStorage(); | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         foreach (Periodicity::cases() as $interval) { | 
					
						
							| 
									
										
										
										
											2024-12-22 20:37:54 +01:00
										 |  |  |             $periodicityClass  = __NAMESPACE__."\\Periodicity\\{$interval->name}"; | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |             self::$intervals[] = $interval->name; | 
					
						
							|  |  |  |             self::$intervalMap->attach($interval, new $periodicityClass()); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-12-20 19:35:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         return self::$intervalMap; | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-17 20:33:26 +02:00
										 |  |  |     private function skipInterval(int $skip): int | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2023-07-15 16:02:42 +02:00
										 |  |  |         return self::DEFAULT_INTERVAL + $skip; | 
					
						
							| 
									
										
										
										
											2023-07-03 00:08:14 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | } |