|
11 | 11 |
|
12 | 12 | use OCP\AppFramework\Db\Entity; |
13 | 13 | use OCP\DB\Types; |
| 14 | +use Psr\Container\ContainerExceptionInterface; |
| 15 | +use Psr\Container\NotFoundExceptionInterface; |
| 16 | +use Recurr\Exception\InvalidRRule; |
| 17 | +use Recurr\RecurrenceCollection; |
| 18 | +use Recurr\Rule; |
| 19 | +use Recurr\Transformer\Constraint\AfterConstraint; |
| 20 | +use function OCP\Log\logger; |
14 | 21 |
|
15 | 22 | /** |
16 | 23 | * @method \string getUserId() |
17 | 24 | * @method \void setUserId(string $userId) |
18 | 25 | * @method \string getPrompt() |
19 | 26 | * @method \void setPrompt(string $prompt) |
20 | 27 | * @method \string getRecurrence() |
21 | | - * @method \void setRecurrence(string $recurrence) |
22 | 28 | * @method \int getStartsAt() |
23 | 29 | * @method \void setStartsAt(int $startsAt) |
24 | 30 | * @method \int getCreatedAt() |
@@ -89,11 +95,41 @@ public function jsonSerialize() { |
89 | 95 | ]; |
90 | 96 | } |
91 | 97 |
|
| 98 | + /** |
| 99 | + * @throws \InvalidArgumentException |
| 100 | + */ |
| 101 | + public function setRecurrence(string $recurrence): void { |
| 102 | + try { |
| 103 | + new Rule($recurrence); |
| 104 | + } catch (InvalidRRule $e) { |
| 105 | + throw new \InvalidArgumentException('Invalid recurrence rule: ' . $recurrence, previous: $e); |
| 106 | + } |
| 107 | + $this->setter('recurrence', [$recurrence]); |
| 108 | + } |
| 109 | + |
92 | 110 | /** |
93 | 111 | * Evaluates the recurrence rule and checks if a run is due |
94 | 112 | */ |
95 | 113 | public function isDueToRun(\DateTimeImmutable $now): bool { |
96 | | - // TODO: Use an actual algorithm here |
97 | | - return true; |
| 114 | + try { |
| 115 | + $startsAt = new \DateTime('@' . $this->getStartsAt()); |
| 116 | + // Find recurrences after the last run or after the current time if this assignment has never run |
| 117 | + $rule = new Rule($this->getRecurrence(), $startsAt); |
| 118 | + $transformer = new \Recurr\Transformer\ArrayTransformer(); |
| 119 | + $constraint = new AfterConstraint($this->getLastRunAt() !== 0 ? new \DateTime('@' . $this->getLastRunAt()) : $startsAt, true); |
| 120 | + /** @var RecurrenceCollection $collection */ |
| 121 | + $collection = $transformer->transform($rule, $constraint); |
| 122 | + if ($collection->isEmpty()) { |
| 123 | + return false; |
| 124 | + } |
| 125 | + $nextRecurrence = $collection->first(); |
| 126 | + if ($nextRecurrence->getStart()->getTimestamp() <= $now->getTimestamp() && $nextRecurrence->getStart()->getTimestamp() > $this->getLastRunAt()) { |
| 127 | + return true; |
| 128 | + } |
| 129 | + } catch (InvalidRRule|\Exception|NotFoundExceptionInterface|ContainerExceptionInterface $e) { |
| 130 | + // this should not happen, as we validate the rule on setRecurrence, but just in case, we catch the exception and log it |
| 131 | + logger('assistant')->error($e->getMessage(), ['exception' => $e]); |
| 132 | + } |
| 133 | + return false; |
98 | 134 | } |
99 | 135 | } |
0 commit comments