diff --git a/CHANGELOG.md b/CHANGELOG.md index 8357a6c7c..ec82b3eaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- [#233](https://github.com/os2display/display-api-service/pull/233) + - Added calendar api feed source tests for modifiers. + - Changed to use PCRE pattern instead of custom pattern building and fixed modifier bugs for calendar api feed source. - [#229](https://github.com/os2display/display-api-service/pull/229) - Adds options to set paths to component and admin files from path to the json config file. - [#225](https://github.com/os2display/display-api-service/pull/225) diff --git a/docs/calender-api-feed.md b/docs/calender-api-feed.md index e6a1ca010..eeab566f5 100644 --- a/docs/calender-api-feed.md +++ b/docs/calender-api-feed.md @@ -136,20 +136,19 @@ Modifiers can be set up to modify the output of the feed. Two types of modifiers are available: -* EXCLUDE_IF_TITLE_NOT_CONTAINS: Removes entries from the feed if the title not contain the trigger word. -* REPLACE_TITLE_IF_CONTAINS: Changes the title if it contains the trigger word. +* EXCLUDE_IF_TITLE_NOT_CONTAINS: Removes entries from the feed if the title does not contain the pattern. +* REPLACE_TITLE_IF_CONTAINS: Changes the title if it contains the pattern. Parameters: * type: EXCLUDE_IF_TITLE_NOT_CONTAINS or REPLACE_TITLE_IF_CONTAINS * id: Unique identifier for the modifier. * title: Display name when showing the modifier in the admin. -* description: Help text for the modifier. +* description: Description of the modifier. * activateInFeed: Should this filter be optional? If false the rule will always apply. -* trigger: The string that should trigger the modifier. -* replacement: The string to replace the title with. * removeTrigger: Should the trigger word be filtered from the title? -* caseSensitive: Should the trigger word be case-sensitive? +* pattern: The PCRE regular expression. See . +* replacement: The string to replace the title with. See . Examples of modifiers: @@ -161,29 +160,26 @@ Examples of modifiers: "title": "Vis kun begivenheder med (liste) i titlen.", "description": "Denne mulighed fjerner begivenheder, der IKKE har (liste) i titlen. Den fjerner også (liste) fra titlen.", "activateInFeed": true, - "trigger": "(liste)", - "removeTrigger": true, - "caseSensitive": false + "pattern": "\/\\(liste\\)\/i", + "removeTrigger": true }, { "type": "REPLACE_TITLE_IF_CONTAINS", - "id": "replaceIfContainsOptaget", "activateInFeed": false, - "trigger": "(optaget)", + "id": "replaceIfContainsOptaget", + "pattern": "\/\\(optaget\\)\/i", "replacement": "Optaget", - "removeTrigger": true, - "caseSensitive": false + "removeTrigger": true }, { "type": "REPLACE_TITLE_IF_CONTAINS", - "id": "onlyShowAsOptaget", "activateInFeed": true, + "id": "onlyShowAsOptaget", "title": "Overskriv alle titler med Optaget", "description": "Denne mulighed viser alle titler som Optaget.", - "trigger": "", + "pattern": "\/\/", "replacement": "Optaget", - "removeTrigger": false, - "caseSensitive": false + "removeTrigger": false } ] ``` diff --git a/src/Feed/CalendarApiFeedType.php b/src/Feed/CalendarApiFeedType.php index 37210cf59..471416d65 100644 --- a/src/Feed/CalendarApiFeedType.php +++ b/src/Feed/CalendarApiFeedType.php @@ -63,8 +63,6 @@ public function __construct( public function getData(Feed $feed): array { try { - $results = []; - $configuration = $feed->getConfiguration(); $enabledModifiers = $configuration['enabledModifiers'] ?? []; @@ -76,62 +74,28 @@ public function getData(Feed $feed): array } $resources = $configuration['resources']; - foreach ($resources as $resource) { - $events = $this->getResourceEvents($resource); - - /** @var CalendarEvent $event */ - foreach ($events as $event) { - $title = $event->title; - - // Modify title according to event modifiers. - foreach ($this->eventModifiers as $modifier) { - // Make it configurable in the Feed if the modifiers should be enabled. - if ($modifier['activateInFeed'] && !in_array($modifier['id'], $enabledModifiers)) { - continue; - } - - if (self::EXCLUDE_IF_TITLE_NOT_CONTAINS == $modifier['type']) { - $match = preg_match('/'.$modifier['trigger'].'/'.(!$modifier['caseSensitive'] ? 'i' : ''), $title); - - if ($modifier['removeTrigger']) { - $title = str_replace($modifier['trigger'], '', $title); - } - - if (!$match) { - continue; - } - } - - if (self::REPLACE_TITLE_IF_CONTAINS == $modifier['type']) { - $match = preg_match('/'.$modifier['trigger'].'/'.(!$modifier['caseSensitive'] ? 'i' : ''), $title); - - if ($modifier['removeTrigger']) { - $title = str_replace($modifier['trigger'], '', $title); - } - - if ($match) { - $title = $modifier['replacement']; - } - } - } - $title = trim($title); + $events = []; - $results[] = [ - 'id' => Ulid::generate(), - 'title' => $title, - 'startTime' => $event->startTimeTimestamp, - 'endTime' => $event->endTimeTimestamp, - 'resourceTitle' => $event->resourceDisplayName, - 'resourceId' => $event->resourceId, - ]; - } + foreach ($resources as $resource) { + $events += $this->getResourceEvents($resource); } + $modifiedResults = static::applyModifiersToEvents($events, $this->eventModifiers, $enabledModifiers); + + $resultsAsArray = array_map(fn (CalendarEvent $event) => [ + 'id' => Ulid::generate(), + 'title' => $event->title, + 'startTime' => $event->startTimeTimestamp, + 'endTime' => $event->endTimeTimestamp, + 'resourceTitle' => $event->resourceDisplayName, + 'resourceId' => $event->resourceId, + ], $modifiedResults); + // Sort bookings by start time. - usort($results, fn (array $a, array $b) => $a['startTime'] > $b['startTime'] ? 1 : -1); + usort($resultsAsArray, fn (array $a, array $b) => $a['startTime'] > $b['startTime'] ? 1 : -1); - return $results; + return $resultsAsArray; } catch (\Throwable $throwable) { $this->logger->error('{code}: {message}', [ 'code' => $throwable->getCode(), @@ -142,6 +106,54 @@ public function getData(Feed $feed): array return []; } + public static function applyModifiersToEvents(array $events, array $eventModifiers, array $enabledModifiers): array + { + $results = []; + + /** @var CalendarEvent $event */ + foreach ($events as $event) { + $title = $event->title; + + // Modify title according to event modifiers. + foreach ($eventModifiers as $modifier) { + // Make it configurable in the Feed if the modifiers should be enabled. + if ($modifier['activateInFeed'] && !in_array($modifier['id'], $enabledModifiers)) { + continue; + } + + $pattern = $modifier['pattern']; + + if (self::EXCLUDE_IF_TITLE_NOT_CONTAINS == $modifier['type']) { + $match = preg_match($pattern, $title); + + if (!$match) { + continue 2; + } + + if ($modifier['removeTrigger']) { + $title = preg_replace($pattern, '', $title); + } + } + + if (self::REPLACE_TITLE_IF_CONTAINS == $modifier['type']) { + $match = preg_match($pattern, $title); + + if ($match) { + $title = $modifier['replacement']; + } + } + } + + $title = trim($title); + + $event->title = $title; + + $results[] = $event; + } + + return $results; + } + /** * {@inheritDoc} */ diff --git a/tests/Feed/CalendarApiFeedTypeData.php b/tests/Feed/CalendarApiFeedTypeData.php new file mode 100644 index 000000000..6b997f50f --- /dev/null +++ b/tests/Feed/CalendarApiFeedTypeData.php @@ -0,0 +1,79 @@ +events[] = new CalendarEvent( + 'id1', + 'title1', + 1, + 2, + 'resourse1', + 'Resource 1' + ); + $this->events[] = new CalendarEvent( + 'id2', + 'title2 (optaget)', + 3, + 4, + 'resourse1', + 'Resource 1' + ); + $this->events[] = new CalendarEvent( + 'id3', + 'title3 (lISTe)', + 5, + 6, + 'resourse1', + 'Resource 1' + ); + $this->events[] = new CalendarEvent( + 'id4', + 'title4 (lISTe) (optaGET)', + 7, + 8, + 'resourse1', + 'Resource 1' + ); + + $this->modifiers[] = [ + 'type' => 'EXCLUDE_IF_TITLE_NOT_CONTAINS', + 'id' => 'excludeIfNotContainsListe', + 'title' => 'Vis kun begivenheder med (liste) i titlen.', + 'description' => 'Denne mulighed fjerner begivenheder, der IKKE har (liste) i titlen. Den fjerner også (liste) fra titlen.', + 'activateInFeed' => true, + 'pattern' => '/\(liste\)/i', + 'removeTrigger' => true, + ]; + + $this->modifiers[] = [ + 'type' => 'REPLACE_TITLE_IF_CONTAINS', + 'activateInFeed' => false, + 'id' => 'replaceIfContainsOptaget', + 'pattern' => '/\(optaget\)/i', + 'replacement' => 'Optaget', + 'removeTrigger' => true, + ]; + + $this->modifiers[] = [ + 'type' => 'REPLACE_TITLE_IF_CONTAINS', + 'activateInFeed' => true, + 'id' => 'onlyShowAsOptaget', + 'title' => 'Overskriv alle titler med Optaget', + 'description' => 'Denne mulighed viser alle titler som Optaget.', + 'pattern' => '//', + 'replacement' => 'Optaget', + 'removeTrigger' => false, + ]; + } +} diff --git a/tests/Feed/CalendarApiFeedTypeTest.php b/tests/Feed/CalendarApiFeedTypeTest.php new file mode 100644 index 000000000..ba4a9c525 --- /dev/null +++ b/tests/Feed/CalendarApiFeedTypeTest.php @@ -0,0 +1,40 @@ +events, $data->modifiers, ['excludeIfNotContainsListe']); + + $this->assertEquals(2, count($result)); + $this->assertEquals('title3', $result[0]->title); + $this->assertEquals('Optaget', $result[1]->title); + + $data = new CalendarApiFeedTypeData(); + + $result = CalendarApiFeedType::applyModifiersToEvents($data->events, $data->modifiers, ['onlyShowAsOptaget']); + + $this->assertEquals(4, count($result)); + $this->assertEquals('Optaget', $result[0]->title); + $this->assertEquals('Optaget', $result[1]->title); + $this->assertEquals('Optaget', $result[2]->title); + $this->assertEquals('Optaget', $result[3]->title); + + $data = new CalendarApiFeedTypeData(); + + $result = CalendarApiFeedType::applyModifiersToEvents($data->events, $data->modifiers, ['excludeIfNotContainsListe', 'onlyShowAsOptaget']); + + $this->assertEquals(2, count($result)); + $this->assertEquals('Optaget', $result[0]->title); + $this->assertEquals('Optaget', $result[1]->title); + } +}