From c936033feb742f7cf32f3d05361327b8b6b76894 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:04:41 +0200 Subject: [PATCH 01/47] Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a25a4add..a404ea749 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.5.2] - 2025-09-04 + - [#260](https://github.com/os2display/display-api-service/pull/260) - Changed how exceptions are handled in InstantBook. From ca077e47e1f5bd3258e8ec38c08fd0189aea7dd7 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Thu, 25 Sep 2025 09:55:08 +0200 Subject: [PATCH 02/47] Update Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a404ea749..1e084301a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -## [2.5.2] - 2025-09-04 +## [2.5.2] - 2025-09-25 - [#260](https://github.com/os2display/display-api-service/pull/260) - Changed how exceptions are handled in InstantBook. From 2b85f2689c5d691ce9ca81f505b44049dd5307b9 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Fri, 23 May 2025 10:27:03 +0200 Subject: [PATCH 03/47] Initial commit --- src/Feed/BrndFeedType.php | 260 +++++++++++++++++++++ src/Feed/FeedOutputModels.php | 23 +- src/Feed/SourceType/Brnd/ApiClient.php | 175 ++++++++++++++ src/Feed/SourceType/Brnd/BrndException.php | 11 + src/Feed/SourceType/Brnd/SecretsDTO.php | 33 +++ 5 files changed, 501 insertions(+), 1 deletion(-) create mode 100644 src/Feed/BrndFeedType.php create mode 100644 src/Feed/SourceType/Brnd/ApiClient.php create mode 100644 src/Feed/SourceType/Brnd/BrndException.php create mode 100644 src/Feed/SourceType/Brnd/SecretsDTO.php diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php new file mode 100644 index 000000000..0d42f2c04 --- /dev/null +++ b/src/Feed/BrndFeedType.php @@ -0,0 +1,260 @@ +feedService->getFeedSourceConfigUrl($feedSource, 'sport-center'); + + return [ + [ + 'key' => 'brnd-sport-center-id', + 'input' => 'input', + 'type' => 'text', + 'name' => 'sport_center_id', + 'label' => 'Sport Center ID', + 'formGroupClasses' => 'mb-3', + ], + ]; + } + + public function getData(Feed $feed): array + { + $result = [ + 'title' => 'BRND Booking', + 'entries' => [], + ]; + + $configuration = $feed->getConfiguration(); + $feedSource = $feed->getFeedSource(); + + if (null == $feedSource) { + return $result; + } + + $secrets = new SecretsDTO($feedSource); + + $baseUri = $secrets->apiBaseUri; + $recipients = $configuration['recipients'] ?? []; + $publishers = $configuration['publishers'] ?? []; + $pageSize = isset($configuration['page_size']) ? (int) $configuration['page_size'] : 10; + + if (empty($baseUri) || 0 === count($recipients)) { + return $result; + } + + $feedSource = $feed->getFeedSource(); + + if (null === $feedSource) { + return $result; + } + + $entries = $this->apiClient->getFeedEntriesNews($feedSource, $recipients, $publishers, $pageSize); + + foreach ($entries as $entry) { + $item = new Item(); + $item->setTitle($entry->fields->title); + + $crawler = new Crawler($entry->fields->description); + $summary = ''; + foreach ($crawler as $domElement) { + $summary .= $domElement->textContent; + } + $item->setSummary($summary); + + $item->setPublicId((string) $entry->id); + + $link = sprintf('%s/feedentry/%s', $baseUri, $entry->id); + $item->setLink($link); + + if (null !== $entry->fields->body) { + $crawler = new Crawler($entry->fields->body); + $content = ''; + foreach ($crawler as $domElement) { + $content .= $domElement->textContent; + } + } else { + $content = $item->getSummary(); + } + $item->setContent($content); + + $updated = $entry->updated ?? $entry->publishDate; + $item->setLastModified(new \DateTime($updated)); + + $author = new Item\Author(); + $author->setName($entry->publisher->name); + $item->setAuthor($author); + + if (null !== $entry->fields->galleryItems) { + try { + $galleryItems = json_decode($entry->fields->galleryItems, true, 512, JSON_THROW_ON_ERROR); + } catch (\JsonException) { + $galleryItems = []; + } + + foreach ($galleryItems as $galleryItem) { + $media = new Item\Media(); + + $large = sprintf('%s/api/files/%s/thumbnail/large', $baseUri, $galleryItem['id']); + $media->setUrl($large); + + $small = sprintf('%s/api/files/%s/thumbnail/small', $baseUri, $galleryItem['id']); + $media->setThumbnail($small); + + $item->addMedia($media); + } + } + + foreach ($entry->recipients as $recipient) { + $category = new Category(); + $category->setLabel($recipient->name); + + $item->addCategory($category); + } + + $result['entries'][] = $item->toArray(); + } + + return $result; + } + + public function getConfigOptions(Request $request, FeedSource $feedSource, string $name): ?array + { + switch ($name) { + case 'allowed-recipients': + $allowedIds = $feedSource->getSecrets()['allowed_recipients'] ?? []; + $allGroupOptions = $this->getConfigOptions($request, $feedSource, 'recipients'); + + if (null === $allGroupOptions) { + return []; + } + + return array_values(array_filter($allGroupOptions, fn (ConfigOption $group) => in_array($group->value, $allowedIds))); + case 'recipients': + $id = self::getIdKey($feedSource); + + /** @var CacheItemInterface $cacheItem */ + $cacheItem = $this->feedsCache->getItem('colibo_feed_entry_groups_'.$id); + + if ($cacheItem->isHit()) { + $groups = $cacheItem->get(); + } else { + $groups = $this->apiClient->getSearchGroups($feedSource); + + $groups = array_map(fn (array $item) => new ConfigOption( + Ulid::generate(), + sprintf('%s (%d)', $item['model']['title'], $item['model']['id']), + (string) $item['model']['id'] + ), $groups); + + usort($groups, fn ($a, $b) => strcmp($a->title, $b->title)); + + $cacheItem->set($groups); + $cacheItem->expiresAfter(self::CACHE_TTL); + $this->feedsCache->save($cacheItem->set($groups)); + } + + return $groups; + default: + return null; + } + } + + public function getRequiredSecrets(): array + { + return [ + 'api_base_uri' => [ + 'type' => 'string', + 'exposeValue' => true, + ], + 'client_id' => [ + 'type' => 'string', + ], + 'client_secret' => [ + 'type' => 'string', + ], + 'allowed_recipients' => [ + 'type' => 'string_array', + 'exposeValue' => true, + ], + ]; + } + + public function getRequiredConfiguration(): array + { + return ['recipients', 'page_size']; + } + + public function getSupportedFeedOutputType(): string + { + return self::SUPPORTED_FEED_TYPE; + } + + public function getSchema(): array + { + return [ + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'type' => 'object', + 'properties' => [ + 'api_base_uri' => [ + 'type' => 'string', + 'format' => 'uri', + ], + 'client_id' => [ + 'type' => 'string', + ], + 'client_secret' => [ + 'type' => 'string', + ], + 'allowed_recipients' => [ + 'type' => 'array', + 'items' => [ + 'type' => 'string', + ], + ], + ], + 'required' => ['api_base_uri', 'client_id', 'client_secret'], + ]; + } + + public static function getIdKey(FeedSource $feedSource): string + { + $ulid = $feedSource->getId(); + assert(null !== $ulid); + + return $ulid->toBase32(); + } +} diff --git a/src/Feed/FeedOutputModels.php b/src/Feed/FeedOutputModels.php index 0458c7231..283bf3a2b 100644 --- a/src/Feed/FeedOutputModels.php +++ b/src/Feed/FeedOutputModels.php @@ -61,4 +61,25 @@ class FeedOutputModels * ] */ final public const string RSS_OUTPUT = 'rss'; -} + + /** + * Data example: + * + * [ + * { + * bookingcode: "BKN-367310", + * analeg: "Humlehøj Hallen", + * date: "2025-05-01", + * displayStart: "09:00", + * displayEnd: "10:45", + * displayTime: "09:00 - 10:45", + * bookingBy: "Børnegården Humle-Tumle", + * start: "2025-05-01T09:00", + * end: "2025-05-01T10:45", + * activityGroupName: "Kampsport", + * activityName: "Brydning", + * } + * ] + */ + final public const string BRND_BOOKING_OUTPUT = 'brnd-booking'; +} \ No newline at end of file diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php new file mode 100644 index 000000000..c19a5c1e8 --- /dev/null +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -0,0 +1,175 @@ + */ + private array $apiClients = []; + + public function __construct( + private readonly CacheItemPoolInterface $feedsCache, + private readonly LoggerInterface $logger, + ) {} + + + /** + * Retrieve bookings based on the given feed source and sportCenterId. + * + * @param FeedSource $feedSource + * @param string $sportCenterId + * @param string $startDate + * @param string $endDate + * + * @return array + */ + public function getBookingInfo(FeedSource $feedSource, string $sportCenterId): array + { + try { + $responseData = $this->getBookingInfoPage($feedSource, $sportCenterId)->toArray(); + + $bookings = $responseData['data']; + + return $bookings; + } catch (\Throwable $throwable) { + $this->logger->error('{code}: {message}', [ + 'code' => $throwable->getCode(), + 'message' => $throwable->getMessage(), + ]); + + return []; + } + } + + /** + * @param FeedSource $feedSource + * @param string $sportCenterId + * @param string $startDate + * @param string $endDate + * + * @return ResponseInterface + * + * @throws BrndException + */ + private function getBookingInfoPage( + FeedSource $feedSource, + string $sportCenterId, + ?string $startDate = null, + ?string $endDate = null + ): ResponseInterface { + $startDate = $startDate ?? date('Y-m-d'); + $endDate = $endDate ?? date('Y-m-d'); + + try { + $client = $this->getApiClient($feedSource); + + return $client->request('POST', '/v1.0/booking-info', [ + 'body' => [ + 'sportCenterId' => $sportCenterId, + 'startDate' => $startDate, + 'endDate' => $endDate, + ], + ]); + } catch (BrndException $exception) { + throw $exception; + } catch (\Throwable $throwable) { + throw new BrndException($throwable->getMessage(), (int) $throwable->getCode(), $throwable); + } + } + + /** + * Get an authenticated scoped API client for the given FeedSource. + * + * @param FeedSource $feedSource + * + * @return HttpClientInterface + * + * @throws BrndException + */ + private function getApiClient(FeedSource $feedSource): HttpClientInterface + { + $id = BrndFeedType::getIdKey($feedSource); + + if (array_key_exists($id, $this->apiClients)) { + return $this->apiClients[$id]; + } + + $secrets = new SecretsDTO($feedSource); + $this->apiClients[$id] = HttpClient::createForBaseUri($secrets->apiBaseUri)->withOptions([ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Authorization' => 'Bearer '.$this->fetchToken($feedSource), + 'Accept' => '*/*', + ], + ]); + + return $this->apiClients[$id]; + } + + /** + * Get the auth token for the given FeedSource. + * + * @param FeedSource $feedSource + * + * @return string + * + * @throws BrndException + */ + private function fetchToken(FeedSource $feedSource): string + { + $id = BrndFeedType::getIdKey($feedSource); + + /** @var CacheItemInterface $cacheItem */ + $cacheItem = $this->feedsCache->getItem('brnd_token_'.$id); + + if ($cacheItem->isHit()) { + /** @var string $token */ + $token = $cacheItem->get(); + } else { + try { + $secrets = new SecretsDTO($feedSource); + $client = HttpClient::createForBaseUri($secrets->apiBaseUri); + + $response = $client->request('POST', '/v1.0/generate-token', [ + 'headers' => [ + 'Content-Type' => 'application/json', + 'Accept' => '*/*', + ], + 'body' => [ + 'associationType' => self::ASSOCIATION_TYPE, + 'apiAuthKey' => $secrets->apiAuthKey, + ], + ]); + + $content = $response->getContent(); + $contentDecoded = json_decode($content, false, 512, JSON_THROW_ON_ERROR); + + $token = $contentDecoded->access_token; + + // Expire cache 5 min before token expire + $expireSeconds = intval($contentDecoded->expires_in - 300); + + $cacheItem->set($token); + $cacheItem->expiresAfter($expireSeconds); + $this->feedsCache->save($cacheItem); + } catch (\Throwable $throwable) { + throw new BrndException($throwable->getMessage(), (int) $throwable->getCode(), $throwable); + } + } + + return $token; + } +} diff --git a/src/Feed/SourceType/Brnd/BrndException.php b/src/Feed/SourceType/Brnd/BrndException.php new file mode 100644 index 000000000..d5cbd67b6 --- /dev/null +++ b/src/Feed/SourceType/Brnd/BrndException.php @@ -0,0 +1,11 @@ +getSecrets(); + + if (null === $secrets) { + throw new \RuntimeException('No secrets found for feed source.'); + } + + if (!isset($secrets['api_base_uri'], $secrets['api_auth_key'])) { + throw new \RuntimeException('Missing required secrets for feed source.'); + } + + if (false === filter_var($secrets['api_base_uri'], FILTER_VALIDATE_URL)) { + throw new \RuntimeException('Invalid api_endpoint.'); + } + + $this->apiBaseUri = rtrim((string) $secrets['api_base_uri'], '/'); + $this->apiAuthKey = $secrets['api_auth_key']; + } +} From 45b3f9421eb82612dc583079fab893da0cdc9282 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 27 May 2025 16:11:50 +0200 Subject: [PATCH 04/47] Change API endpoint --- src/Feed/BrndFeedType.php | 161 ++++++------------------ src/Feed/FeedOutputModels.php | 25 ++-- src/Feed/SourceType/Brnd/ApiClient.php | 52 +++++--- src/Feed/SourceType/Brnd/SecretsDTO.php | 4 +- 4 files changed, 86 insertions(+), 156 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 0d42f2c04..478f8a15c 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -27,7 +27,7 @@ class BrndFeedType implements FeedTypeInterface { public const int CACHE_TTL = 3600; - final public const string SUPPORTED_FEED_TYPE = FeedOutputModels::RSS_OUTPUT; + final public const string SUPPORTED_FEED_TYPE = FeedOutputModels::BRND_BOOKING_OUTPUT; public function __construct( private readonly FeedService $feedService, @@ -55,7 +55,7 @@ public function getData(Feed $feed): array { $result = [ 'title' => 'BRND Booking', - 'entries' => [], + 'bookings' => [], ]; $configuration = $feed->getConfiguration(); @@ -68,11 +68,9 @@ public function getData(Feed $feed): array $secrets = new SecretsDTO($feedSource); $baseUri = $secrets->apiBaseUri; - $recipients = $configuration['recipients'] ?? []; - $publishers = $configuration['publishers'] ?? []; - $pageSize = isset($configuration['page_size']) ? (int) $configuration['page_size'] : 10; + $sportCenterId = $configuration['sport_center_id'] ?? null; - if (empty($baseUri) || 0 === count($recipients)) { + if (empty($baseUri) || empty($sportCenterId)) { return $result; } @@ -82,115 +80,36 @@ public function getData(Feed $feed): array return $result; } - $entries = $this->apiClient->getFeedEntriesNews($feedSource, $recipients, $publishers, $pageSize); - - foreach ($entries as $entry) { - $item = new Item(); - $item->setTitle($entry->fields->title); - - $crawler = new Crawler($entry->fields->description); - $summary = ''; - foreach ($crawler as $domElement) { - $summary .= $domElement->textContent; - } - $item->setSummary($summary); - - $item->setPublicId((string) $entry->id); - - $link = sprintf('%s/feedentry/%s', $baseUri, $entry->id); - $item->setLink($link); - - if (null !== $entry->fields->body) { - $crawler = new Crawler($entry->fields->body); - $content = ''; - foreach ($crawler as $domElement) { - $content .= $domElement->textContent; - } - } else { - $content = $item->getSummary(); - } - $item->setContent($content); - - $updated = $entry->updated ?? $entry->publishDate; - $item->setLastModified(new \DateTime($updated)); - - $author = new Item\Author(); - $author->setName($entry->publisher->name); - $item->setAuthor($author); - - if (null !== $entry->fields->galleryItems) { - try { - $galleryItems = json_decode($entry->fields->galleryItems, true, 512, JSON_THROW_ON_ERROR); - } catch (\JsonException) { - $galleryItems = []; - } - - foreach ($galleryItems as $galleryItem) { - $media = new Item\Media(); - - $large = sprintf('%s/api/files/%s/thumbnail/large', $baseUri, $galleryItem['id']); - $media->setUrl($large); - - $small = sprintf('%s/api/files/%s/thumbnail/small', $baseUri, $galleryItem['id']); - $media->setThumbnail($small); - - $item->addMedia($media); - } - } - - foreach ($entry->recipients as $recipient) { - $category = new Category(); - $category->setLabel($recipient->name); - - $item->addCategory($category); - } - - $result['entries'][] = $item->toArray(); - } + $bookings = $this->apiClient->getInfomonitorBookingsDetails($feedSource, $sportCenterId); + + $result['bookings'] = array_map([$this, 'parseBrndBooking'], $bookings); return $result; } - public function getConfigOptions(Request $request, FeedSource $feedSource, string $name): ?array + private function parseBrndBooking(array $booking): array { - switch ($name) { - case 'allowed-recipients': - $allowedIds = $feedSource->getSecrets()['allowed_recipients'] ?? []; - $allGroupOptions = $this->getConfigOptions($request, $feedSource, 'recipients'); - - if (null === $allGroupOptions) { - return []; - } - - return array_values(array_filter($allGroupOptions, fn (ConfigOption $group) => in_array($group->value, $allowedIds))); - case 'recipients': - $id = self::getIdKey($feedSource); - - /** @var CacheItemInterface $cacheItem */ - $cacheItem = $this->feedsCache->getItem('colibo_feed_entry_groups_'.$id); - - if ($cacheItem->isHit()) { - $groups = $cacheItem->get(); - } else { - $groups = $this->apiClient->getSearchGroups($feedSource); - - $groups = array_map(fn (array $item) => new ConfigOption( - Ulid::generate(), - sprintf('%s (%d)', $item['model']['title'], $item['model']['id']), - (string) $item['model']['id'] - ), $groups); - - usort($groups, fn ($a, $b) => strcmp($a->title, $b->title)); - - $cacheItem->set($groups); - $cacheItem->expiresAfter(self::CACHE_TTL); - $this->feedsCache->save($cacheItem->set($groups)); - } + return [ + 'bookingcode' => $booking['ansøgning'] ?? '', + 'remarks' => $booking['bemærkninger'] ?? '', + 'date' => $booking['dato'] ?? '', + 'start' => $booking['starttid'] ?? '', + 'end' => $booking['sluttid'] ?? '', + 'complex' => $booking['anlæg'] ?? '', + 'area' => $booking['område'] ?? '', + 'facility' => $booking['facilitet'] ?? '', + 'activity' => $booking['aktivitet'] ?? '', + 'team' => $booking['hold'] ?? '', + 'status' => $booking['status'] ?? '', + 'checkIn' => $booking['checK_IN'] ?? '', + 'bookingBy' => $booking['ansøgt_af'] ?? '', + 'changingRooms' => $booking['omklædningsrum'] ?? '', + ]; + } - return $groups; - default: - return null; - } + public function getConfigOptions(Request $request, FeedSource $feedSource, string $name): ?array + { + return null; } public function getRequiredSecrets(): array @@ -200,22 +119,18 @@ public function getRequiredSecrets(): array 'type' => 'string', 'exposeValue' => true, ], - 'client_id' => [ + 'company_id' => [ 'type' => 'string', ], - 'client_secret' => [ + 'api_auth_key' => [ 'type' => 'string', ], - 'allowed_recipients' => [ - 'type' => 'string_array', - 'exposeValue' => true, - ], ]; } public function getRequiredConfiguration(): array { - return ['recipients', 'page_size']; + return ['sport_center_id']; } public function getSupportedFeedOutputType(): string @@ -233,20 +148,14 @@ public function getSchema(): array 'type' => 'string', 'format' => 'uri', ], - 'client_id' => [ + 'company_id' => [ 'type' => 'string', ], - 'client_secret' => [ + 'api_auth_key' => [ 'type' => 'string', ], - 'allowed_recipients' => [ - 'type' => 'array', - 'items' => [ - 'type' => 'string', - ], - ], ], - 'required' => ['api_base_uri', 'client_id', 'client_secret'], + 'required' => ['api_base_uri', 'company_id', 'api_auth_key'], ]; } @@ -258,3 +167,5 @@ public static function getIdKey(FeedSource $feedSource): string return $ulid->toBase32(); } } + + diff --git a/src/Feed/FeedOutputModels.php b/src/Feed/FeedOutputModels.php index 283bf3a2b..e34cc96e8 100644 --- a/src/Feed/FeedOutputModels.php +++ b/src/Feed/FeedOutputModels.php @@ -67,17 +67,20 @@ class FeedOutputModels * * [ * { - * bookingcode: "BKN-367310", - * analeg: "Humlehøj Hallen", - * date: "2025-05-01", - * displayStart: "09:00", - * displayEnd: "10:45", - * displayTime: "09:00 - 10:45", - * bookingBy: "Børnegården Humle-Tumle", - * start: "2025-05-01T09:00", - * end: "2025-05-01T10:45", - * activityGroupName: "Kampsport", - * activityName: "Brydning", + * bookingcode: "BKN-363612", + * remarks: "Kinesisk undervisning", + * date: "05/25/2025 00:00:00", + * start: "08:30:00.0000000", + * end: "12:30:00.0000000", + * complex: "Multikulturhuset", + * area: "Mødelokaler", + * facility: "M3.2 - Max 6 personer", + * activity: "Møder", + * team: "", + * status: "Tildelt tid", + * checkIn: "0", + * bookingBy: "Engangsbruger", + * changingRooms: "" * } * ] */ diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php index c19a5c1e8..f0651aa09 100644 --- a/src/Feed/SourceType/Brnd/ApiClient.php +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -15,7 +15,11 @@ class ApiClient { - private const string ASSOCIATION_TYPE = 'Company'; + private const string AUTH_ASSOCIATION_TYPE = 'Company'; + private const string BOOKINGS_ASSOCIATION_TYPE = 'Sportcenter'; + private const int STATUS_CANCELLED = 5; + private const int STATUS_ALLOCATED = 4; + /** @var array */ private array $apiClients = []; @@ -27,21 +31,19 @@ public function __construct( /** - * Retrieve bookings based on the given feed source and sportCenterId. + * Retrieve todays bookings from Infomonitor Booking API for a given sportCenterId. * * @param FeedSource $feedSource * @param string $sportCenterId - * @param string $startDate - * @param string $endDate * * @return array */ - public function getBookingInfo(FeedSource $feedSource, string $sportCenterId): array + public function getInfomonitorBookingsDetails(FeedSource $feedSource, string $sportCenterId): array { try { - $responseData = $this->getBookingInfoPage($feedSource, $sportCenterId)->toArray(); + $responseData = $this->getInfomonitorBookingsDetailsData($feedSource, $sportCenterId)->toArray(); - $bookings = $responseData['data']; + $bookings = $responseData['data']['infoBookingDetails']; return $bookings; } catch (\Throwable $throwable) { @@ -57,30 +59,42 @@ public function getBookingInfo(FeedSource $feedSource, string $sportCenterId): a /** * @param FeedSource $feedSource * @param string $sportCenterId - * @param string $startDate - * @param string $endDate + * @param string|null $date Optional. Defaults to today if not provided (Y-m-d). + * @param string|null $startTime Optional. Time in HH:MM format. Defaults to empty string if not provided (no time filter applied). + * @param string|null $endTime Optional. Time in HH:MM format. Defaults to empty string if not provided (no time filter applied). + * @param int[]|null $bookingStatusCodes Optional. Array of booking status codes to filter by. * * @return ResponseInterface * * @throws BrndException */ - private function getBookingInfoPage( + private function getInfomonitorBookingsDetailsData( FeedSource $feedSource, string $sportCenterId, - ?string $startDate = null, - ?string $endDate = null + ?string $date = null, + ?string $startTime = null, + ?string $endTime = null, + ?array $bookingStatusCodes = null ): ResponseInterface { - $startDate = $startDate ?? date('Y-m-d'); - $endDate = $endDate ?? date('Y-m-d'); + $secrets = new SecretsDTO($feedSource); + $defaultStatusCodes = [self::STATUS_ALLOCATED, self::STATUS_CANCELLED]; + $date = $date ?? date('Y-m-d'); + $startTime = $startTime ?? ''; + $endTime = $endTime ?? ''; + $bookingStatusCodes = implode(',', $bookingStatusCodes ?? $defaultStatusCodes); try { $client = $this->getApiClient($feedSource); - return $client->request('POST', '/v1.0/booking-info', [ + return $client->request('POST', '/v1.0/get-infomonitor-bookings-details', [ 'body' => [ - 'sportCenterId' => $sportCenterId, - 'startDate' => $startDate, - 'endDate' => $endDate, + 'companyID' => $secrets->companyId, + 'associationID' => $sportCenterId, + 'associationType' => self::BOOKINGS_ASSOCIATION_TYPE, + 'date' => $date, + 'startTime' => $startTime, + 'endTime' => $endTime, + 'statusID' => $bookingStatusCodes, ], ]); } catch (BrndException $exception) { @@ -149,7 +163,7 @@ private function fetchToken(FeedSource $feedSource): string 'Accept' => '*/*', ], 'body' => [ - 'associationType' => self::ASSOCIATION_TYPE, + 'associationType' => self::AUTH_ASSOCIATION_TYPE, 'apiAuthKey' => $secrets->apiAuthKey, ], ]); diff --git a/src/Feed/SourceType/Brnd/SecretsDTO.php b/src/Feed/SourceType/Brnd/SecretsDTO.php index 2e5d266ad..261c20de9 100644 --- a/src/Feed/SourceType/Brnd/SecretsDTO.php +++ b/src/Feed/SourceType/Brnd/SecretsDTO.php @@ -10,6 +10,7 @@ { public string $apiBaseUri; public string $apiAuthKey; + public string $companyId; public function __construct(FeedSource $feedSource) { @@ -19,7 +20,7 @@ public function __construct(FeedSource $feedSource) throw new \RuntimeException('No secrets found for feed source.'); } - if (!isset($secrets['api_base_uri'], $secrets['api_auth_key'])) { + if (!isset($secrets['api_base_uri'], $secrets['company_id'], $secrets['api_auth_key'])) { throw new \RuntimeException('Missing required secrets for feed source.'); } @@ -28,6 +29,7 @@ public function __construct(FeedSource $feedSource) } $this->apiBaseUri = rtrim((string) $secrets['api_base_uri'], '/'); + $this->companyId = $secrets['company_id']; $this->apiAuthKey = $secrets['api_auth_key']; } } From e90f378dca84cd025a2e506f7fbf318d7c1eed03 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 3 Jun 2025 14:32:07 +0200 Subject: [PATCH 05/47] Change secrets settings --- src/Feed/BrndFeedType.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 478f8a15c..a82862c04 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -121,9 +121,11 @@ public function getRequiredSecrets(): array ], 'company_id' => [ 'type' => 'string', + 'exposeValue' => true, ], 'api_auth_key' => [ 'type' => 'string', + 'exposeValue' => true, ], ]; } From 0519fee5b67b4033e297031f0a0075feebe7ca57 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 17 Jun 2025 13:59:35 +0200 Subject: [PATCH 06/47] Change time formats --- src/Feed/BrndFeedType.php | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index a82862c04..7617fdacf 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -45,7 +45,7 @@ public function getAdminFormOptions(FeedSource $feedSource): array 'input' => 'input', 'type' => 'text', 'name' => 'sport_center_id', - 'label' => 'Sport Center ID', + 'label' => 'Sportcenter ID', 'formGroupClasses' => 'mb-3', ], ]; @@ -89,12 +89,29 @@ public function getData(Feed $feed): array private function parseBrndBooking(array $booking): array { + // Parse start time + $startDateTime = null; + if (!empty($booking['date']) && !empty($booking['starttid'])) { + $startDateTime = \DateTimeImmutable::createFromFormat( + 'm/d/Y H:i:s.u', + preg_replace('/\.\d+$/', '', $booking['date']) . ' ' . substr($booking['starttid'], 0, 8) . '.0' + ); + } + + // Parse end time + $endDateTime = null; + if (!empty($booking['date']) && !empty($booking['sluttid'])) { + $endDateTime = \DateTimeImmutable::createFromFormat( + 'm/d/Y H:i:s.u', + preg_replace('/\.\d+$/', '', $booking['date']) . ' ' . substr($booking['sluttid'], 0, 8) . '.0' + ); + } + return [ 'bookingcode' => $booking['ansøgning'] ?? '', 'remarks' => $booking['bemærkninger'] ?? '', - 'date' => $booking['dato'] ?? '', - 'start' => $booking['starttid'] ?? '', - 'end' => $booking['sluttid'] ?? '', + 'startTime' => $startDateTime ? $startDateTime->getTimestamp() : null, + 'endTime' => $endDateTime ? $endDateTime->getTimestamp() : null, 'complex' => $booking['anlæg'] ?? '', 'area' => $booking['område'] ?? '', 'facility' => $booking['facilitet'] ?? '', From 5d60da15f46096d30774be76a5f88046ca3c93e0 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 1 Jul 2025 15:05:53 +0200 Subject: [PATCH 07/47] Various bugfixes --- src/Feed/BrndFeedType.php | 21 ++++++++------- src/Feed/SourceType/Brnd/ApiClient.php | 36 +++++++++++++++----------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 7617fdacf..954f654b2 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -91,20 +91,21 @@ private function parseBrndBooking(array $booking): array { // Parse start time $startDateTime = null; - if (!empty($booking['date']) && !empty($booking['starttid'])) { - $startDateTime = \DateTimeImmutable::createFromFormat( - 'm/d/Y H:i:s.u', - preg_replace('/\.\d+$/', '', $booking['date']) . ' ' . substr($booking['starttid'], 0, 8) . '.0' - ); + if (!empty($booking['dato']) && !empty($booking['starttid'])) { + // Trim starttid to 6 digits after dot for microseconds + $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); + $dateOnly = substr($booking['dato'], 0, 10); + $dateTimeString = $dateOnly . ' ' . $starttid; + $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); } // Parse end time $endDateTime = null; - if (!empty($booking['date']) && !empty($booking['sluttid'])) { - $endDateTime = \DateTimeImmutable::createFromFormat( - 'm/d/Y H:i:s.u', - preg_replace('/\.\d+$/', '', $booking['date']) . ' ' . substr($booking['sluttid'], 0, 8) . '.0' - ); + if (!empty($booking['dato']) && !empty($booking['sluttid'])) { + $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); + $dateOnly = substr($booking['dato'], 0, 10); + $dateTimeString = $dateOnly . ' ' . $sluttid; + $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); } return [ diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php index f0651aa09..79dbf62d8 100644 --- a/src/Feed/SourceType/Brnd/ApiClient.php +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -19,7 +19,7 @@ class ApiClient private const string BOOKINGS_ASSOCIATION_TYPE = 'Sportcenter'; private const int STATUS_CANCELLED = 5; private const int STATUS_ALLOCATED = 4; - + private const int TOKEN_TTL = 1200; /** @var array */ private array $apiClients = []; @@ -29,7 +29,6 @@ public function __construct( private readonly LoggerInterface $logger, ) {} - /** * Retrieve todays bookings from Infomonitor Booking API for a given sportCenterId. * @@ -38,12 +37,22 @@ public function __construct( * * @return array */ - public function getInfomonitorBookingsDetails(FeedSource $feedSource, string $sportCenterId): array + public function getInfomonitorBookingsDetails( + FeedSource $feedSource, + string $sportCenterId + ): array { try { $responseData = $this->getInfomonitorBookingsDetailsData($feedSource, $sportCenterId)->toArray(); - $bookings = $responseData['data']['infoBookingDetails']; + $bookings = []; + if (isset($responseData['data']) && is_array($responseData['data'])) { + foreach ($responseData['data'] as $item) { + if (isset($item['infoBookingDetails']) && is_array($item['infoBookingDetails'])) { + $bookings = array_merge($bookings, $item['infoBookingDetails']); + } + } + } return $bookings; } catch (\Throwable $throwable) { @@ -87,7 +96,7 @@ private function getInfomonitorBookingsDetailsData( $client = $this->getApiClient($feedSource); return $client->request('POST', '/v1.0/get-infomonitor-bookings-details', [ - 'body' => [ + 'json' => [ 'companyID' => $secrets->companyId, 'associationID' => $sportCenterId, 'associationType' => self::BOOKINGS_ASSOCIATION_TYPE, @@ -156,26 +165,24 @@ private function fetchToken(FeedSource $feedSource): string try { $secrets = new SecretsDTO($feedSource); $client = HttpClient::createForBaseUri($secrets->apiBaseUri); - - $response = $client->request('POST', '/v1.0/generate-token', [ + $requestOptions = [ 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => '*/*', ], - 'body' => [ + 'json' => [ 'associationType' => self::AUTH_ASSOCIATION_TYPE, 'apiAuthKey' => $secrets->apiAuthKey, ], - ]); + ]; + $response = $client->request('POST', '/v1.0/generate-token', $requestOptions); - $content = $response->getContent(); + $content = $response->getContent(false); // Don't throw on non-2xx $contentDecoded = json_decode($content, false, 512, JSON_THROW_ON_ERROR); - - $token = $contentDecoded->access_token; + $token = $contentDecoded->data->access_token; // Expire cache 5 min before token expire - $expireSeconds = intval($contentDecoded->expires_in - 300); - + $expireSeconds = intval(self::TOKEN_TTL - 300); $cacheItem->set($token); $cacheItem->expiresAfter($expireSeconds); $this->feedsCache->save($cacheItem); @@ -183,7 +190,6 @@ private function fetchToken(FeedSource $feedSource): string throw new BrndException($throwable->getMessage(), (int) $throwable->getCode(), $throwable); } } - return $token; } } From 5a27c01ab5635b602ba5ba74ae276b4006f0e09a Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Fri, 4 Jul 2025 13:39:00 +0200 Subject: [PATCH 08/47] Better data example --- src/Feed/FeedOutputModels.php | 43 +++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/Feed/FeedOutputModels.php b/src/Feed/FeedOutputModels.php index e34cc96e8..e47dd4ea9 100644 --- a/src/Feed/FeedOutputModels.php +++ b/src/Feed/FeedOutputModels.php @@ -62,27 +62,42 @@ class FeedOutputModels */ final public const string RSS_OUTPUT = 'rss'; - /** + /** * Data example: - * * [ * { - * bookingcode: "BKN-363612", - * remarks: "Kinesisk undervisning", - * date: "05/25/2025 00:00:00", - * start: "08:30:00.0000000", - * end: "12:30:00.0000000", - * complex: "Multikulturhuset", - * area: "Mødelokaler", - * facility: "M3.2 - Max 6 personer", - * activity: "Møder", - * team: "", + * activity: "Svømning", + * area: "Svømmehal", + * bookingBy: "Offentlig svømning", + * bookingcode: "BKN-363973", + * changingRooms: "", + * checkIn: "0", + * complex: "Humlehøj Hallen", + * endTime: 1751615100, + * facility: "Svømmehal", + * remarks: "", + * startTime: 1751608800, * status: "Tildelt tid", + * team: "" + * }, + * { + * activity: "Undervisning", + * area: "Mødelokaler", + * bookingBy: "Svømmeklubben Sønderborg", + * bookingcode: "BKN-388946", + * changingRooms: "", * checkIn: "0", - * bookingBy: "Engangsbruger", - * changingRooms: "" + * complex: "Humlehøj Hallen", + * endTime: 1751641200, + * facility: "Mødelokale 1+2", + * remarks: "", + * startTime: 1751630400, + * status: "Tildelt tid", + * team: "" * } * ] + * + * Start/end time are unix timestamps. */ final public const string BRND_BOOKING_OUTPUT = 'brnd-booking'; } \ No newline at end of file From ac26287565c354ef66ea42f8d5fdfadde01bbc34 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 18 Sep 2025 13:37:04 +0200 Subject: [PATCH 09/47] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e084301a..59c1bdf1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ All notable changes to this project will be documented in this file. - [#260](https://github.com/os2display/display-api-service/pull/260) - Changed how exceptions are handled in InstantBook. +- [#313](https://github.com/os2display/display-api-service/pull/313) + - Add BRND booking feed type ## [2.5.1] - 2025-06-23 From a90f6c731ed5cd5e5cdc9b2cc556c6e02169085e Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 18 Sep 2025 13:37:57 +0200 Subject: [PATCH 10/47] Update CHANGELOG --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59c1bdf1f..983a23e39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,13 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - +- [#313](https://github.com/os2display/display-api-service/pull/313) + - Add BRND booking feed type + ## [2.5.2] - 2025-09-25 - [#260](https://github.com/os2display/display-api-service/pull/260) - Changed how exceptions are handled in InstantBook. -- [#313](https://github.com/os2display/display-api-service/pull/313) - - Add BRND booking feed type ## [2.5.1] - 2025-06-23 From a56cc6eb731a18a1c4088cbb3ae59d61c6b81b2c Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 18 Sep 2025 13:43:15 +0200 Subject: [PATCH 11/47] Fix markdownlint errors --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 983a23e39..552027526 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] + - [#313](https://github.com/os2display/display-api-service/pull/313) - Add BRND booking feed type From 64f6dadbb6964b584d4b248819e1cf40f7a70ccb Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 18 Sep 2025 13:49:13 +0200 Subject: [PATCH 12/47] Fix psalm errors --- src/Feed/BrndFeedType.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 954f654b2..1d6bbdaff 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -70,7 +70,7 @@ public function getData(Feed $feed): array $baseUri = $secrets->apiBaseUri; $sportCenterId = $configuration['sport_center_id'] ?? null; - if (empty($baseUri) || empty($sportCenterId)) { + if ($baseUri === null || $baseUri === '' || $sportCenterId === null || $sportCenterId === '') { return $result; } @@ -91,7 +91,7 @@ private function parseBrndBooking(array $booking): array { // Parse start time $startDateTime = null; - if (!empty($booking['dato']) && !empty($booking['starttid'])) { + if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { // Trim starttid to 6 digits after dot for microseconds $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); $dateOnly = substr($booking['dato'], 0, 10); @@ -101,7 +101,7 @@ private function parseBrndBooking(array $booking): array // Parse end time $endDateTime = null; - if (!empty($booking['dato']) && !empty($booking['sluttid'])) { + if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); $dateOnly = substr($booking['dato'], 0, 10); $dateTimeString = $dateOnly . ' ' . $sluttid; From 13597d1cb2d9929aaafea67b7ccdcfc96acda6f6 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 18 Sep 2025 14:00:42 +0200 Subject: [PATCH 13/47] Fix psalm errors --- src/Feed/BrndFeedType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 1d6bbdaff..e34361dc6 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -70,7 +70,7 @@ public function getData(Feed $feed): array $baseUri = $secrets->apiBaseUri; $sportCenterId = $configuration['sport_center_id'] ?? null; - if ($baseUri === null || $baseUri === '' || $sportCenterId === null || $sportCenterId === '') { + if ($baseUri === '' || $sportCenterId === null || $sportCenterId === '') { return $result; } From fb5d3c0f56896e19ea21021999b7fd22eef7feb5 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 23 Sep 2025 12:36:41 +0200 Subject: [PATCH 14/47] Correct php-cs-fixer errors --- src/Feed/BrndFeedType.php | 18 +++++------------- src/Feed/FeedOutputModels.php | 2 +- src/Feed/SourceType/Brnd/ApiClient.php | 8 ++++---- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index e34361dc6..a736f0b44 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -6,17 +6,11 @@ use App\Entity\Tenant\Feed; use App\Entity\Tenant\FeedSource; -use App\Feed\OutputModel\ConfigOption; use App\Feed\SourceType\Brnd\ApiClient; use App\Feed\SourceType\Brnd\SecretsDTO; use App\Service\FeedService; -use FeedIo\Feed\Item; -use FeedIo\Feed\Node\Category; -use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\DomCrawler\Crawler; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Uid\Ulid; /** * Brnd Bookingsystem Feed. @@ -70,7 +64,7 @@ public function getData(Feed $feed): array $baseUri = $secrets->apiBaseUri; $sportCenterId = $configuration['sport_center_id'] ?? null; - if ($baseUri === '' || $sportCenterId === null || $sportCenterId === '') { + if ('' === $baseUri || null === $sportCenterId || '' === $sportCenterId) { return $result; } @@ -81,7 +75,7 @@ public function getData(Feed $feed): array } $bookings = $this->apiClient->getInfomonitorBookingsDetails($feedSource, $sportCenterId); - + $result['bookings'] = array_map([$this, 'parseBrndBooking'], $bookings); return $result; @@ -95,7 +89,7 @@ private function parseBrndBooking(array $booking): array // Trim starttid to 6 digits after dot for microseconds $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly . ' ' . $starttid; + $dateTimeString = $dateOnly.' '.$starttid; $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); } @@ -104,7 +98,7 @@ private function parseBrndBooking(array $booking): array if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly . ' ' . $sluttid; + $dateTimeString = $dateOnly.' '.$sluttid; $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); } @@ -186,6 +180,4 @@ public static function getIdKey(FeedSource $feedSource): string return $ulid->toBase32(); } -} - - +} \ No newline at end of file diff --git a/src/Feed/FeedOutputModels.php b/src/Feed/FeedOutputModels.php index e47dd4ea9..af1090139 100644 --- a/src/Feed/FeedOutputModels.php +++ b/src/Feed/FeedOutputModels.php @@ -96,7 +96,7 @@ class FeedOutputModels * team: "" * } * ] - * + * * Start/end time are unix timestamps. */ final public const string BRND_BOOKING_OUTPUT = 'brnd-booking'; diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php index 79dbf62d8..f65c76080 100644 --- a/src/Feed/SourceType/Brnd/ApiClient.php +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -39,9 +39,8 @@ public function __construct( */ public function getInfomonitorBookingsDetails( FeedSource $feedSource, - string $sportCenterId - ): array - { + string $sportCenterId, + ): array { try { $responseData = $this->getInfomonitorBookingsDetailsData($feedSource, $sportCenterId)->toArray(); @@ -83,7 +82,7 @@ private function getInfomonitorBookingsDetailsData( ?string $date = null, ?string $startTime = null, ?string $endTime = null, - ?array $bookingStatusCodes = null + ?array $bookingStatusCodes = null, ): ResponseInterface { $secrets = new SecretsDTO($feedSource); $defaultStatusCodes = [self::STATUS_ALLOCATED, self::STATUS_CANCELLED]; @@ -190,6 +189,7 @@ private function fetchToken(FeedSource $feedSource): string throw new BrndException($throwable->getMessage(), (int) $throwable->getCode(), $throwable); } } + return $token; } } From e2b4b67d2da45d1b2f4301c6652a6990a6844dca Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 23 Sep 2025 13:03:37 +0200 Subject: [PATCH 15/47] Correct php-cs-fixer errors --- src/Feed/BrndFeedType.php | 2 +- src/Feed/FeedOutputModels.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index a736f0b44..26a2fa805 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -180,4 +180,4 @@ public static function getIdKey(FeedSource $feedSource): string return $ulid->toBase32(); } -} \ No newline at end of file +} diff --git a/src/Feed/FeedOutputModels.php b/src/Feed/FeedOutputModels.php index af1090139..b318f75ea 100644 --- a/src/Feed/FeedOutputModels.php +++ b/src/Feed/FeedOutputModels.php @@ -100,4 +100,4 @@ class FeedOutputModels * Start/end time are unix timestamps. */ final public const string BRND_BOOKING_OUTPUT = 'brnd-booking'; -} \ No newline at end of file +} From b1126f3f671407523bb7eed28d0f5f67fd8efbb5 Mon Sep 17 00:00:00 2001 From: agnetemoos Date: Thu, 30 Oct 2025 12:37:49 +0100 Subject: [PATCH 16/47] Update src/Feed/BrndFeedType.php Co-authored-by: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> --- src/Feed/BrndFeedType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 26a2fa805..263af9822 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -137,7 +137,7 @@ public function getRequiredSecrets(): array ], 'api_auth_key' => [ 'type' => 'string', - 'exposeValue' => true, + 'exposeValue' => false, ], ]; } From 2ac6e374a5aba51dffb99fc2401b58b0bb6418bc Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 30 Oct 2025 13:11:15 +0100 Subject: [PATCH 17/47] Improve error handling --- src/Feed/BrndFeedType.php | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 263af9822..7b69cc2a3 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -86,20 +86,34 @@ private function parseBrndBooking(array $booking): array // Parse start time $startDateTime = null; if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { - // Trim starttid to 6 digits after dot for microseconds - $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); - $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly.' '.$starttid; - $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + try { + // Trim starttid to 6 digits after dot for microseconds + $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); + $dateOnly = substr($booking['dato'], 0, 10); + $dateTimeString = $dateOnly.' '.$starttid; + $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + if (false === $startDateTime) { + $startDateTime = null; + } + } catch (\ValueError) { + $startDateTime = null; + } } // Parse end time $endDateTime = null; if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { - $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); - $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly.' '.$sluttid; - $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + try { + $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); + $dateOnly = substr($booking['dato'], 0, 10); + $dateTimeString = $dateOnly.' '.$sluttid; + $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + if (false === $endDateTime) { + $endDateTime = null; + } + } catch (\ValueError) { + $endDateTime = null; + } } return [ From 7a1df7253c243256062744ae7f4c256384329778 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 30 Oct 2025 13:21:24 +0100 Subject: [PATCH 18/47] Validate required fields --- src/Feed/BrndFeedType.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 7b69cc2a3..e5ea22a92 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -76,7 +76,16 @@ public function getData(Feed $feed): array $bookings = $this->apiClient->getInfomonitorBookingsDetails($feedSource, $sportCenterId); - $result['bookings'] = array_map([$this, 'parseBrndBooking'], $bookings); + $result['bookings'] = array_reduce($bookings, function (array $carry, array $booking): array { + $parsedBooking = $this->parseBrndBooking($booking); + + // Validate that booking has required fields + if (!empty($parsedBooking['bookingcode']) && !empty($parsedBooking['bookingBy'])) { + $carry[] = $parsedBooking; + } + + return $carry; + }, []); return $result; } From f9ae36d56bea849fffa62387de3944437a92d698 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 30 Oct 2025 13:43:11 +0100 Subject: [PATCH 19/47] Refactor getData method to improve error handling --- src/Feed/BrndFeedType.php | 53 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index e5ea22a92..213f15597 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -52,41 +52,40 @@ public function getData(Feed $feed): array 'bookings' => [], ]; - $configuration = $feed->getConfiguration(); - $feedSource = $feed->getFeedSource(); + try { + $configuration = $feed->getConfiguration(); + $feedSource = $feed->getFeedSource(); - if (null == $feedSource) { - return $result; - } + if (null == $feedSource) { + return $result; + } - $secrets = new SecretsDTO($feedSource); + $secrets = new SecretsDTO($feedSource); - $baseUri = $secrets->apiBaseUri; - $sportCenterId = $configuration['sport_center_id'] ?? null; + $baseUri = $secrets->apiBaseUri; + $sportCenterId = $configuration['sport_center_id'] ?? null; - if ('' === $baseUri || null === $sportCenterId || '' === $sportCenterId) { - return $result; - } + if ('' === $baseUri || null === $sportCenterId || '' === $sportCenterId) { + return $result; + } - $feedSource = $feed->getFeedSource(); + $bookings = $this->apiClient->getInfomonitorBookingsDetails($feedSource, $sportCenterId); - if (null === $feedSource) { - return $result; + $result['bookings'] = array_reduce($bookings, function (array $carry, array $booking): array { + $parsedBooking = $this->parseBrndBooking($booking); + + // Validate that booking has required fields + if (!empty($parsedBooking['bookingcode']) && !empty($parsedBooking['bookingBy'])) { + $carry[] = $parsedBooking; + } + + return $carry; + }, []); + } catch (\Throwable) { + // Silently catch all exceptions and return empty result + // $result is already initialized with empty bookings array } - $bookings = $this->apiClient->getInfomonitorBookingsDetails($feedSource, $sportCenterId); - - $result['bookings'] = array_reduce($bookings, function (array $carry, array $booking): array { - $parsedBooking = $this->parseBrndBooking($booking); - - // Validate that booking has required fields - if (!empty($parsedBooking['bookingcode']) && !empty($parsedBooking['bookingBy'])) { - $carry[] = $parsedBooking; - } - - return $carry; - }, []); - return $result; } From b06ca777ed5e18e3addf869bfc208d31ce99a1f5 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Thu, 30 Oct 2025 14:19:50 +0100 Subject: [PATCH 20/47] Remove trailing white space --- src/Feed/BrndFeedType.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 213f15597..e43c33a8e 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -73,12 +73,12 @@ public function getData(Feed $feed): array $result['bookings'] = array_reduce($bookings, function (array $carry, array $booking): array { $parsedBooking = $this->parseBrndBooking($booking); - + // Validate that booking has required fields if (!empty($parsedBooking['bookingcode']) && !empty($parsedBooking['bookingBy'])) { $carry[] = $parsedBooking; } - + return $carry; }, []); } catch (\Throwable) { From 2bba4a92e369cec5abae7598b6fbe4e98ad5b676 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Fri, 31 Oct 2025 09:08:19 +0100 Subject: [PATCH 21/47] Improve variable naming --- src/Feed/BrndFeedType.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index e43c33a8e..229ae2f64 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -95,10 +95,10 @@ private function parseBrndBooking(array $booking): array $startDateTime = null; if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { try { - // Trim starttid to 6 digits after dot for microseconds - $starttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); + // Trim starttime to 6 digits after dot for microseconds + $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly.' '.$starttid; + $dateTimeString = $dateOnly.' '.$startTimeString; $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); if (false === $startDateTime) { $startDateTime = null; @@ -112,9 +112,9 @@ private function parseBrndBooking(array $booking): array $endDateTime = null; if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { try { - $sluttid = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); + $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); $dateOnly = substr($booking['dato'], 0, 10); - $dateTimeString = $dateOnly.' '.$sluttid; + $dateTimeString = $dateOnly.' '.$endTimeString; $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); if (false === $endDateTime) { $endDateTime = null; From 83d4d817d2174429ef360a61dc4eb8fe949d6490 Mon Sep 17 00:00:00 2001 From: agnetemoos Date: Mon, 3 Nov 2025 14:18:49 +0100 Subject: [PATCH 22/47] Update src/Feed/BrndFeedType.php Co-authored-by: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> --- src/Feed/BrndFeedType.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 229ae2f64..a19e49518 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -81,7 +81,8 @@ public function getData(Feed $feed): array return $carry; }, []); - } catch (\Throwable) { + } catch (\Throwable $throwable) { + $this->logger->error($throwable->getMessage()); // Silently catch all exceptions and return empty result // $result is already initialized with empty bookings array } From 308827863fea542bfd596b8ad91a5dd602ed8177 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Mon, 3 Nov 2025 14:26:41 +0100 Subject: [PATCH 23/47] Add LoggerInterface --- src/Feed/BrndFeedType.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index a19e49518..8d6c9536f 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -10,6 +10,7 @@ use App\Feed\SourceType\Brnd\SecretsDTO; use App\Service\FeedService; use Psr\Cache\CacheItemPoolInterface; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; /** @@ -27,6 +28,7 @@ public function __construct( private readonly FeedService $feedService, private readonly ApiClient $apiClient, private readonly CacheItemPoolInterface $feedsCache, + private readonly LoggerInterface $logger, ) {} public function getAdminFormOptions(FeedSource $feedSource): array From e1509fa7e635eba6382f27a39897c8659e139005 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Mon, 3 Nov 2025 14:35:16 +0100 Subject: [PATCH 24/47] Fix indentation --- src/Feed/BrndFeedType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 8d6c9536f..66b0f96e3 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -84,7 +84,7 @@ public function getData(Feed $feed): array return $carry; }, []); } catch (\Throwable $throwable) { - $this->logger->error($throwable->getMessage()); + $this->logger->error($throwable->getMessage()); // Silently catch all exceptions and return empty result // $result is already initialized with empty bookings array } From b0de9c4298396325db0fc8ba305df43ab59b8e95 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Fri, 21 Nov 2025 11:51:53 +0100 Subject: [PATCH 25/47] Remove cancelled status code from default booking status codes in ApiClient --- src/Feed/SourceType/Brnd/ApiClient.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php index f65c76080..147a58b8e 100644 --- a/src/Feed/SourceType/Brnd/ApiClient.php +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -85,7 +85,7 @@ private function getInfomonitorBookingsDetailsData( ?array $bookingStatusCodes = null, ): ResponseInterface { $secrets = new SecretsDTO($feedSource); - $defaultStatusCodes = [self::STATUS_ALLOCATED, self::STATUS_CANCELLED]; + $defaultStatusCodes = [self::STATUS_ALLOCATED]; $date = $date ?? date('Y-m-d'); $startTime = $startTime ?? ''; $endTime = $endTime ?? ''; From 6001d8411d4ee084f130138c293b6d7883c456aa Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:38:08 +0100 Subject: [PATCH 26/47] 5740: Composer update --- composer.lock | 2883 ++++++++++++++++++++++++++++--------------------- 1 file changed, 1624 insertions(+), 1259 deletions(-) diff --git a/composer.lock b/composer.lock index ac9344e10..dfa0f841a 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "api-platform/core", - "version": "v3.4.4", + "version": "v3.4.17", "source": { "type": "git", "url": "https://github.com/api-platform/core.git", - "reference": "77d3ff3e8ddf88546eaf288a399d11f130553606" + "reference": "c5fb664d17ed9ae919394514ea69a5039d2ad9ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/api-platform/core/zipball/77d3ff3e8ddf88546eaf288a399d11f130553606", - "reference": "77d3ff3e8ddf88546eaf288a399d11f130553606", + "url": "https://api.github.com/repos/api-platform/core/zipball/c5fb664d17ed9ae919394514ea69a5039d2ad9ab", + "reference": "c5fb664d17ed9ae919394514ea69a5039d2ad9ab", "shasum": "" }, "require": { @@ -44,7 +44,7 @@ "elasticsearch/elasticsearch": ">=8.0,<8.4", "phpspec/prophecy": "<1.15", "phpunit/phpunit": "<9.5", - "symfony/framework-bundle": "6.4.6 || 7.1.6", + "symfony/framework-bundle": "6.4.6 || 7.0.6", "symfony/var-exporter": "<6.1.1" }, "replace": { @@ -107,7 +107,7 @@ "justinrainbow/json-schema": "^5.2.1", "phpspec/prophecy-phpunit": "^2.0", "phpstan/extension-installer": "^1.1", - "phpstan/phpdoc-parser": "^1.13", + "phpstan/phpdoc-parser": "^1.13|^2.0", "phpstan/phpstan": "^1.10", "phpstan/phpstan-doctrine": "^1.0", "phpstan/phpstan-phpunit": "^1.0", @@ -174,13 +174,6 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-3.4": "3.4.x-dev", - "dev-main": "4.0.x-dev" - }, - "symfony": { - "require": "^6.4 || ^7.1" - }, "pmu": { "projects": [ "./src/*/composer.json", @@ -188,8 +181,15 @@ ] }, "thanks": { - "name": "api-platform/api-platform", - "url": "https://github.com/api-platform/api-platform" + "url": "https://github.com/api-platform/api-platform", + "name": "api-platform/api-platform" + }, + "symfony": { + "require": "^6.4 || ^7.1" + }, + "branch-alias": { + "dev-3.4": "3.4.x-dev", + "dev-main": "4.0.x-dev" } }, "autoload": { @@ -223,9 +223,9 @@ ], "support": { "issues": "https://github.com/api-platform/core/issues", - "source": "https://github.com/api-platform/core/tree/v3.4.4" + "source": "https://github.com/api-platform/core/tree/v3.4.17" }, - "time": "2024-10-19T10:05:07+00:00" + "time": "2025-04-07T08:40:57+00:00" }, { "name": "clue/ndjson-react", @@ -366,16 +366,16 @@ }, { "name": "composer/pcre", - "version": "3.3.1", + "version": "3.3.2", "source": { "type": "git", "url": "https://github.com/composer/pcre.git", - "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", - "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e", + "reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e", "shasum": "" }, "require": { @@ -385,19 +385,19 @@ "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpstan/phpstan": "^1.11.10", - "phpstan/phpstan-strict-rules": "^1.1", + "phpstan/phpstan": "^1.12 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.x-dev" - }, "phpstan": { "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-main": "3.x-dev" } }, "autoload": { @@ -425,7 +425,7 @@ ], "support": { "issues": "https://github.com/composer/pcre/issues", - "source": "https://github.com/composer/pcre/tree/3.3.1" + "source": "https://github.com/composer/pcre/tree/3.3.2" }, "funding": [ { @@ -441,20 +441,20 @@ "type": "tidelift" } ], - "time": "2024-08-27T18:44:43+00:00" + "time": "2024-11-12T16:29:46+00:00" }, { "name": "composer/semver", - "version": "3.4.3", + "version": "3.4.4", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12" + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", - "reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12", + "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95", + "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95", "shasum": "" }, "require": { @@ -506,7 +506,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.4.3" + "source": "https://github.com/composer/semver/tree/3.4.4" }, "funding": [ { @@ -516,13 +516,9 @@ { "url": "https://github.com/composer", "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/composer/composer", - "type": "tidelift" } ], - "time": "2024-09-19T14:15:21+00:00" + "time": "2025-08-20T19:15:30+00:00" }, { "name": "composer/xdebug-handler", @@ -660,6 +656,7 @@ "issues": "https://github.com/alexdebril/feed-io/issues", "source": "https://github.com/alexdebril/feed-io/tree/v6.0.3" }, + "abandoned": "php-feed-io/feed-io", "time": "2023-10-16T14:12:49+00:00" }, { @@ -753,33 +750,34 @@ "type": "tidelift" } ], + "abandoned": true, "time": "2022-05-20T20:07:39+00:00" }, { "name": "doctrine/collections", - "version": "2.2.2", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "d8af7f248c74f195f7347424600fd9e17b57af59" + "reference": "9acfeea2e8666536edff3d77c531261c63680160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/d8af7f248c74f195f7347424600fd9e17b57af59", - "reference": "d8af7f248c74f195f7347424600fd9e17b57af59", + "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160", + "reference": "9acfeea2e8666536edff3d77c531261c63680160", "shasum": "" }, "require": { "doctrine/deprecations": "^1", - "php": "^8.1" + "php": "^8.1", + "symfony/polyfill-php84": "^1.30" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^14", "ext-json": "*", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.11" + "phpstan/phpstan": "^2.1.30", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpunit/phpunit": "^10.5.58 || ^11.5.42 || ^12.4" }, "type": "library", "autoload": { @@ -823,7 +821,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.2.2" + "source": "https://github.com/doctrine/collections/tree/2.4.0" }, "funding": [ { @@ -839,24 +837,24 @@ "type": "tidelift" } ], - "time": "2024-04-18T06:56:21+00:00" + "time": "2025-10-25T09:18:13+00:00" }, { "name": "doctrine/common", - "version": "3.4.5", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/doctrine/common.git", - "reference": "6c8fef961f67b8bc802ce3e32e3ebd1022907286" + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/6c8fef961f67b8bc802ce3e32e3ebd1022907286", - "reference": "6c8fef961f67b8bc802ce3e32e3ebd1022907286", + "url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5", + "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5", "shasum": "" }, "require": { - "doctrine/persistence": "^2.0 || ^3.0", + "doctrine/persistence": "^2.0 || ^3.0 || ^4.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -914,7 +912,7 @@ ], "support": { "issues": "https://github.com/doctrine/common/issues", - "source": "https://github.com/doctrine/common/tree/3.4.5" + "source": "https://github.com/doctrine/common/tree/3.5.0" }, "funding": [ { @@ -930,44 +928,45 @@ "type": "tidelift" } ], - "time": "2024-10-08T15:53:43+00:00" + "time": "2025-01-01T22:12:03+00:00" }, { "name": "doctrine/dbal", - "version": "3.9.3", + "version": "3.10.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba" + "reference": "65edaca19a752730f290ec2fb89d593cb40afb43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", - "reference": "61446f07fcb522414d6cfd8b1c3e5f9e18c579ba", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/65edaca19a752730f290ec2fb89d593cb40afb43", + "reference": "65edaca19a752730f290ec2fb89d593cb40afb43", "shasum": "" }, "require": { "composer-runtime-api": "^2", - "doctrine/cache": "^1.11|^2.0", "doctrine/deprecations": "^0.5.3|^1", "doctrine/event-manager": "^1|^2", "php": "^7.4 || ^8.0", "psr/cache": "^1|^2|^3", "psr/log": "^1|^2|^3" }, + "conflict": { + "doctrine/cache": "< 1.11" + }, "require-dev": { - "doctrine/coding-standard": "12.0.0", + "doctrine/cache": "^1.11|^2.0", + "doctrine/coding-standard": "14.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.12.6", - "phpstan/phpstan-strict-rules": "^1.6", - "phpunit/phpunit": "9.6.20", - "psalm/plugin-phpunit": "0.18.4", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.2", + "phpstan/phpstan": "2.1.30", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "9.6.29", + "slevomat/coding-standard": "8.24.0", + "squizlabs/php_codesniffer": "4.0.0", "symfony/cache": "^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "vimeo/psalm": "4.30.0" + "symfony/console": "^4.4|^5.4|^6.0|^7.0" }, "suggest": { "symfony/console": "For helpful console commands such as SQL execution and import of files." @@ -1027,7 +1026,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.3" + "source": "https://github.com/doctrine/dbal/tree/3.10.3" }, "funding": [ { @@ -1043,33 +1042,34 @@ "type": "tidelift" } ], - "time": "2024-10-10T17:56:43+00:00" + "time": "2025-10-09T09:05:12+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.3", + "version": "1.1.5", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, + "conflict": { + "phpunit/phpunit": "<=7.5 || >=13" + }, "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" + "doctrine/coding-standard": "^9 || ^12 || ^13", + "phpstan/phpstan": "1.4.10 || 2.1.11", + "phpstan/phpstan-phpunit": "^1.0 || ^2", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "psr/log": "^1 || ^2 || ^3" }, "suggest": { "psr/log": "Allows logging deprecations via PSR-3 logger implementation" @@ -1077,7 +1077,7 @@ "type": "library", "autoload": { "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + "Doctrine\\Deprecations\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1088,68 +1088,69 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + "source": "https://github.com/doctrine/deprecations/tree/1.1.5" }, - "time": "2024-01-30T19:34:25+00:00" + "time": "2025-04-07T20:06:18+00:00" }, { "name": "doctrine/doctrine-bundle", - "version": "2.13.0", + "version": "2.18.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "ca59d84b8e63143ce1aed90cdb333ba329d71563" + "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/ca59d84b8e63143ce1aed90cdb333ba329d71563", - "reference": "ca59d84b8e63143ce1aed90cdb333ba329d71563", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/b769877014de053da0e5cbbb63d0ea2f3b2fea76", + "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76", "shasum": "" }, "require": { - "doctrine/cache": "^1.11 || ^2.0", "doctrine/dbal": "^3.7.0 || ^4.0", - "doctrine/persistence": "^2.2 || ^3", + "doctrine/deprecations": "^1.0", + "doctrine/persistence": "^3.1 || ^4", "doctrine/sql-formatter": "^1.0.1", - "php": "^7.4 || ^8.0", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/doctrine-bridge": "^5.4.19 || ^6.0.7 || ^7.0", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/polyfill-php80": "^1.15", - "symfony/service-contracts": "^1.1.1 || ^2.0 || ^3" + "php": "^8.1", + "symfony/cache": "^6.4 || ^7.0", + "symfony/config": "^6.4 || ^7.0", + "symfony/console": "^6.4 || ^7.0", + "symfony/dependency-injection": "^6.4 || ^7.0", + "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3", + "symfony/framework-bundle": "^6.4 || ^7.0", + "symfony/service-contracts": "^2.5 || ^3" }, "conflict": { "doctrine/annotations": ">=3.0", + "doctrine/cache": "< 1.11", "doctrine/orm": "<2.17 || >=4.0", - "twig/twig": "<1.34 || >=2.0 <2.4" + "symfony/var-exporter": "< 6.4.1 || 7.0.0", + "twig/twig": "<2.13 || >=3.0 <3.0.4" }, "require-dev": { "doctrine/annotations": "^1 || ^2", - "doctrine/coding-standard": "^12", - "doctrine/deprecations": "^1.0", - "doctrine/orm": "^2.17 || ^3.0", + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^14", + "doctrine/orm": "^2.17 || ^3.1", "friendsofphp/proxy-manager-lts": "^1.0", - "phpunit/phpunit": "^9.5.26", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^5", + "phpstan/phpstan": "2.1.1", + "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.53 || ^12.3.10", "psr/log": "^1.1.4 || ^2.0 || ^3.0", - "symfony/phpunit-bridge": "^6.1 || ^7.0", - "symfony/property-info": "^5.4 || ^6.0 || ^7.0", - "symfony/proxy-manager-bridge": "^5.4 || ^6.0 || ^7.0", - "symfony/security-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", - "symfony/string": "^5.4 || ^6.0 || ^7.0", - "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0", - "symfony/validator": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^5.4 || ^6.2 || ^7.0", - "symfony/web-profiler-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0", - "twig/twig": "^1.34 || ^2.12 || ^3.0", - "vimeo/psalm": "^5.15" + "symfony/doctrine-messenger": "^6.4 || ^7.0", + "symfony/expression-language": "^6.4 || ^7.0", + "symfony/messenger": "^6.4 || ^7.0", + "symfony/property-info": "^6.4 || ^7.0", + "symfony/security-bundle": "^6.4 || ^7.0", + "symfony/stopwatch": "^6.4 || ^7.0", + "symfony/string": "^6.4 || ^7.0", + "symfony/twig-bridge": "^6.4 || ^7.0", + "symfony/validator": "^6.4 || ^7.0", + "symfony/var-exporter": "^6.4.1 || ^7.0.1", + "symfony/web-profiler-bundle": "^6.4 || ^7.0", + "symfony/yaml": "^6.4 || ^7.0", + "twig/twig": "^2.14.7 || ^3.0.4" }, "suggest": { "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", @@ -1194,7 +1195,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.13.0" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.1" }, "funding": [ { @@ -1210,54 +1211,47 @@ "type": "tidelift" } ], - "time": "2024-09-01T09:46:40+00:00" + "time": "2025-11-05T14:42:10+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "3.3.1", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0" + "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", - "reference": "715b62c31a5894afcb2b2cdbbc6607d7dd0580c0", + "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/1e380c6dd8ac8488217f39cff6b77e367f1a644b", + "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b", "shasum": "" }, "require": { - "doctrine/doctrine-bundle": "^2.4", + "doctrine/doctrine-bundle": "^2.4 || ^3.0", "doctrine/migrations": "^3.2", - "php": "^7.2|^8.0", + "php": "^7.2 || ^8.0", "symfony/deprecation-contracts": "^2.1 || ^3", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { "composer/semver": "^3.0", - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^12 || ^14", "doctrine/orm": "^2.6 || ^3", - "doctrine/persistence": "^2.0 || ^3 ", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-deprecation-rules": "^1", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^8.5|^9.5", - "psalm/plugin-phpunit": "^0.18.4", - "psalm/plugin-symfony": "^3 || ^5", - "symfony/phpunit-bridge": "^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6 || ^7", - "vimeo/psalm": "^4.30 || ^5.15" + "phpstan/phpstan": "^1.4 || ^2", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1.1 || ^2", + "phpstan/phpstan-symfony": "^1.3 || ^2", + "phpunit/phpunit": "^8.5 || ^9.5", + "symfony/phpunit-bridge": "^6.3 || ^7 || ^8", + "symfony/var-exporter": "^5.4 || ^6 || ^7 || ^8" }, "type": "symfony-bundle", "autoload": { "psr-4": { - "Doctrine\\Bundle\\MigrationsBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Doctrine\\Bundle\\MigrationsBundle\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1286,7 +1280,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.3.1" + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.7.0" }, "funding": [ { @@ -1302,7 +1296,7 @@ "type": "tidelift" } ], - "time": "2024-05-14T20:32:18+00:00" + "time": "2025-11-15T19:02:59+00:00" }, { "name": "doctrine/event-manager", @@ -1397,33 +1391,32 @@ }, { "name": "doctrine/inflector", - "version": "2.0.10", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc" + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc", - "reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^11.0", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.3", - "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25 || ^5.4" + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" }, "type": "library", "autoload": { "psr-4": { - "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" + "Doctrine\\Inflector\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1468,7 +1461,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.10" + "source": "https://github.com/doctrine/inflector/tree/2.1.0" }, "funding": [ { @@ -1484,7 +1477,7 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/instantiator", @@ -1635,16 +1628,16 @@ }, { "name": "doctrine/migrations", - "version": "3.8.2", + "version": "3.9.5", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "5007eb1168691225ac305fe16856755c20860842" + "reference": "1b823afbc40f932dae8272574faee53f2755eac5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/5007eb1168691225ac305fe16856755c20860842", - "reference": "5007eb1168691225ac305fe16856755c20860842", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b823afbc40f932dae8272574faee53f2755eac5", + "reference": "1b823afbc40f932dae8272574faee53f2755eac5", "shasum": "" }, "require": { @@ -1654,29 +1647,29 @@ "doctrine/event-manager": "^1.2 || ^2.0", "php": "^8.1", "psr/log": "^1.1.3 || ^2 || ^3", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0", - "symfony/var-exporter": "^6.2 || ^7.0" + "symfony/console": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/var-exporter": "^6.2 || ^7.0 || ^8.0" }, "conflict": { "doctrine/orm": "<2.12 || >=4" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^14", "doctrine/orm": "^2.13 || ^3", - "doctrine/persistence": "^2 || ^3", + "doctrine/persistence": "^2 || ^3 || ^4", "doctrine/sql-formatter": "^1.0", "ext-pdo_sqlite": "*", "fig/log-test": "^1", - "phpstan/phpstan": "^1.10", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "phpstan/phpstan-strict-rules": "^1.4", - "phpstan/phpstan-symfony": "^1.3", - "phpunit/phpunit": "^10.3", - "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-phpunit": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpstan/phpstan-symfony": "^2", + "phpunit/phpunit": "^10.3 || ^11.0 || ^12.0", + "symfony/cache": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/process": "^5.4 || ^6.0 || ^7.0 || ^8.0", + "symfony/yaml": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "suggest": { "doctrine/sql-formatter": "Allows to generate formatted SQL with the diff command.", @@ -1718,7 +1711,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.8.2" + "source": "https://github.com/doctrine/migrations/tree/3.9.5" }, "funding": [ { @@ -1734,20 +1727,20 @@ "type": "tidelift" } ], - "time": "2024-10-10T21:35:27+00:00" + "time": "2025-11-20T11:15:36+00:00" }, { "name": "doctrine/orm", - "version": "2.20.0", + "version": "2.20.8", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "8ed6c2234aba019f9737a6bcc9516438e62da27c" + "reference": "5bff0919a78c86238536a9b5396024fe3603b5d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/8ed6c2234aba019f9737a6bcc9516438e62da27c", - "reference": "8ed6c2234aba019f9737a6bcc9516438e62da27c", + "url": "https://api.github.com/repos/doctrine/orm/zipball/5bff0919a78c86238536a9b5396024fe3603b5d1", + "reference": "5bff0919a78c86238536a9b5396024fe3603b5d1", "shasum": "" }, "require": { @@ -1774,18 +1767,16 @@ }, "require-dev": { "doctrine/annotations": "^1.13 || ^2", - "doctrine/coding-standard": "^9.0.2 || ^12.0", + "doctrine/coding-standard": "^9.0.2 || ^14.0", "phpbench/phpbench": "^0.16.10 || ^1.0", "phpstan/extension-installer": "~1.1.0 || ^1.4", - "phpstan/phpstan": "~1.4.10 || 1.12.6", - "phpstan/phpstan-deprecation-rules": "^1", + "phpstan/phpstan": "~1.4.10 || 2.1.23", + "phpstan/phpstan-deprecation-rules": "^1 || ^2", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6", "psr/log": "^1 || ^2 || ^3", - "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^4.4 || ^5.4 || ^6.4 || ^7.0", "symfony/var-exporter": "^4.4 || ^5.4 || ^6.2 || ^7.0", - "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "4.30.0 || 5.24.0" + "symfony/yaml": "^3.4 || ^4.0 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { "ext-dom": "Provides support for XSD validation for XML mapping files", @@ -1835,22 +1826,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.20.0" + "source": "https://github.com/doctrine/orm/tree/2.20.8" }, - "time": "2024-10-11T11:47:24+00:00" + "time": "2025-11-10T13:35:45+00:00" }, { "name": "doctrine/persistence", - "version": "3.3.3", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "b337726451f5d530df338fc7f68dee8781b49779" + "reference": "d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/b337726451f5d530df338fc7f68dee8781b49779", - "reference": "b337726451f5d530df338fc7f68dee8781b49779", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0", + "reference": "d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0", "shasum": "" }, "require": { @@ -1862,14 +1853,13 @@ "doctrine/common": "<2.10" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^12 || ^14", "doctrine/common": "^3.0", - "phpstan/phpstan": "1.11.1", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", - "phpunit/phpunit": "^8.5 || ^9.5", - "symfony/cache": "^4.4 || ^5.4 || ^6.0", - "vimeo/psalm": "4.30.0 || 5.24.0" + "phpstan/phpstan": "^1 || 2.1.30", + "phpstan/phpstan-phpunit": "^1 || ^2", + "phpstan/phpstan-strict-rules": "^1 || ^2", + "phpunit/phpunit": "^8.5.38 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0" }, "type": "library", "autoload": { @@ -1918,7 +1908,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.3.3" + "source": "https://github.com/doctrine/persistence/tree/3.4.3" }, "funding": [ { @@ -1934,31 +1924,30 @@ "type": "tidelift" } ], - "time": "2024-06-20T10:14:30+00:00" + "time": "2025-10-21T15:21:39+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.5.1", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "b784cbde727cf806721451dde40eff4fec3bbe86" + "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/b784cbde727cf806721451dde40eff4fec3bbe86", - "reference": "b784cbde727cf806721451dde40eff4fec3bbe86", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a8af23a8e9d622505baa2997465782cbe8bb7fc7", + "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7", "shasum": "" }, "require": { "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^12", - "ergebnis/phpunit-slow-test-detector": "^2.14", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "doctrine/coding-standard": "^14", + "ergebnis/phpunit-slow-test-detector": "^2.20", + "phpstan/phpstan": "^2.1.31", + "phpunit/phpunit": "^10.5.58" }, "bin": [ "bin/sql-formatter" @@ -1988,9 +1977,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.5.1" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.3" }, - "time": "2024-10-21T18:21:57+00:00" + "time": "2025-10-26T09:35:14+00:00" }, { "name": "evenement/evenement", @@ -2041,16 +2030,16 @@ }, { "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "reference": "db9508f7b1474469d9d3c53b86f817e344732678" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/db9508f7b1474469d9d3c53b86f817e344732678", + "reference": "db9508f7b1474469d9d3c53b86f817e344732678", "shasum": "" }, "require": { @@ -2060,10 +2049,10 @@ "fidry/makefile": "^0.2.0", "fidry/php-cs-fixer-config": "^1.1.2", "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", "phpunit/phpunit": "^8.5.31 || ^9.5.26", "webmozarts/strict-phpunit": "^7.5" }, @@ -2090,7 +2079,7 @@ ], "support": { "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.3.0" }, "funding": [ { @@ -2098,20 +2087,20 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2025-08-14T07:29:31+00:00" }, { "name": "firebase/php-jwt", - "version": "v6.10.1", + "version": "v6.11.1", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "500501c2ce893c824c801da135d02661199f60c5" + "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/500501c2ce893c824c801da135d02661199f60c5", - "reference": "500501c2ce893c824c801da135d02661199f60c5", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", + "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", "shasum": "" }, "require": { @@ -2159,63 +2148,63 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.10.1" + "source": "https://github.com/firebase/php-jwt/tree/v6.11.1" }, - "time": "2024-05-18T18:05:11+00:00" + "time": "2025-04-09T20:32:01+00:00" }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.64.0", + "version": "v3.90.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "58dd9c931c785a79739310aef5178928305ffa67" + "reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/58dd9c931c785a79739310aef5178928305ffa67", - "reference": "58dd9c931c785a79739310aef5178928305ffa67", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ad732c2e9299c9743f9c55ae53cc0e7642ab1155", + "reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155", "shasum": "" }, "require": { - "clue/ndjson-react": "^1.0", + "clue/ndjson-react": "^1.3", "composer/semver": "^3.4", - "composer/xdebug-handler": "^3.0.3", + "composer/xdebug-handler": "^3.0.5", "ext-filter": "*", + "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.0", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", - "react/child-process": "^0.6.5", - "react/event-loop": "^1.0", - "react/promise": "^2.0 || ^3.0", - "react/socket": "^1.0", - "react/stream": "^1.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0", - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0", - "symfony/finder": "^5.4 || ^6.0 || ^7.0", - "symfony/options-resolver": "^5.4 || ^6.0 || ^7.0", - "symfony/polyfill-mbstring": "^1.28", - "symfony/polyfill-php80": "^1.28", - "symfony/polyfill-php81": "^1.28", - "symfony/process": "^5.4 || ^6.0 || ^7.0", - "symfony/stopwatch": "^5.4 || ^6.0 || ^7.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3 || ^2.3", - "infection/infection": "^0.29.5", - "justinrainbow/json-schema": "^5.2", - "keradus/cli-executor": "^2.1", - "mikey179/vfsstream": "^1.6.11", - "php-coveralls/php-coveralls": "^2.7", - "php-cs-fixer/accessible-object": "^1.1", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.5", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.5", - "phpunit/phpunit": "^9.6.19 || ^10.5.21 || ^11.2", - "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "react/child-process": "^0.6.6", + "react/event-loop": "^1.5", + "react/socket": "^1.16", + "react/stream": "^1.4", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", + "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.33", + "symfony/polyfill-php80": "^1.33", + "symfony/polyfill-php81": "^1.33", + "symfony/polyfill-php84": "^1.33", + "symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0", + "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" + }, + "require-dev": { + "facile-it/paraunit": "^1.3.1 || ^2.7", + "infection/infection": "^0.31.0", + "justinrainbow/json-schema": "^6.5", + "keradus/cli-executor": "^2.2", + "mikey179/vfsstream": "^1.6.12", + "php-coveralls/php-coveralls": "^2.9", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", + "phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34", + "symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0", + "symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -2256,7 +2245,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.64.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.90.0" }, "funding": [ { @@ -2264,26 +2253,26 @@ "type": "github" } ], - "time": "2024-08-30T23:09:38+00:00" + "time": "2025-11-20T15:15:16+00:00" }, { "name": "friendsofphp/proxy-manager-lts", - "version": "v1.0.18", + "version": "v1.0.19", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/proxy-manager-lts.git", - "reference": "2c8a6cffc3220e99352ad958fe7cf06bf6f7690f" + "reference": "c20299aa9f48a622052964a75c5a4cef017398b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/2c8a6cffc3220e99352ad958fe7cf06bf6f7690f", - "reference": "2c8a6cffc3220e99352ad958fe7cf06bf6f7690f", + "url": "https://api.github.com/repos/FriendsOfPHP/proxy-manager-lts/zipball/c20299aa9f48a622052964a75c5a4cef017398b2", + "reference": "c20299aa9f48a622052964a75c5a4cef017398b2", "shasum": "" }, "require": { "laminas/laminas-code": "~3.4.1|^4.0", "php": ">=7.1", - "symfony/filesystem": "^4.4.17|^5.0|^6.0|^7.0" + "symfony/filesystem": "^4.4.17|^5.0|^6.0|^7.0|^8.0" }, "conflict": { "laminas/laminas-stdlib": "<3.2.1", @@ -2299,8 +2288,8 @@ "type": "library", "extra": { "thanks": { - "name": "ocramius/proxy-manager", - "url": "https://github.com/Ocramius/ProxyManager" + "url": "https://github.com/Ocramius/ProxyManager", + "name": "ocramius/proxy-manager" } }, "autoload": { @@ -2334,7 +2323,7 @@ ], "support": { "issues": "https://github.com/FriendsOfPHP/proxy-manager-lts/issues", - "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.18" + "source": "https://github.com/FriendsOfPHP/proxy-manager-lts/tree/v1.0.19" }, "funding": [ { @@ -2346,38 +2335,38 @@ "type": "tidelift" } ], - "time": "2024-03-20T12:50:41+00:00" + "time": "2025-10-28T10:28:17+00:00" }, { "name": "gesdinet/jwt-refresh-token-bundle", - "version": "v1.3.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/markitosgv/JWTRefreshTokenBundle.git", - "reference": "83d687cc461b4bdae9ffc6efda97464093cae739" + "reference": "8706b0d8dcb26610358ba3328ec412315b55c3cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/markitosgv/JWTRefreshTokenBundle/zipball/83d687cc461b4bdae9ffc6efda97464093cae739", - "reference": "83d687cc461b4bdae9ffc6efda97464093cae739", + "url": "https://api.github.com/repos/markitosgv/JWTRefreshTokenBundle/zipball/8706b0d8dcb26610358ba3328ec412315b55c3cd", + "reference": "8706b0d8dcb26610358ba3328ec412315b55c3cd", "shasum": "" }, "require": { - "doctrine/persistence": "^1.3.3|^2.0|^3.0", + "doctrine/persistence": "^1.3.3|^2.0|^3.0|^4.0", "lexik/jwt-authentication-bundle": "^2.0|^3.0", "php": ">=7.4", - "symfony/config": "^4.4|^5.4|^6.0|^7.0", - "symfony/console": "^4.4|^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^4.4|^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/deprecation-contracts": "^2.1|^3.0", - "symfony/event-dispatcher": "^4.4|^5.4|^6.0|^7.0", - "symfony/http-foundation": "^4.4|^5.4|^6.0|^7.0", - "symfony/http-kernel": "^4.4|^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", "symfony/polyfill-php80": "^1.15", - "symfony/property-access": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-bundle": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-core": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-http": "^4.4|^5.4|^6.0|^7.0" + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/security-bundle": "^5.4|^6.0|^7.0", + "symfony/security-core": "^5.4|^6.0|^7.0", + "symfony/security-http": "^5.4|^6.0|^7.0" }, "conflict": { "doctrine/mongodb-odm": "<2.2", @@ -2387,12 +2376,12 @@ "doctrine/annotations": "^1.13|^2.0", "doctrine/cache": "^1.11|^2.0", "doctrine/mongodb-odm": "^2.2", - "doctrine/orm": "^2.7", + "doctrine/orm": "^2.7|^3.0", "matthiasnoback/symfony-config-test": "^4.2|^5.0", "matthiasnoback/symfony-dependency-injection-test": "^4.2|^5.0", "phpunit/phpunit": "^9.5", - "symfony/cache": "^4.4|^5.4|^6.0|^7.0", - "symfony/security-guard": "^4.4|^5.4" + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/security-guard": "^5.4" }, "type": "symfony-bundle", "extra": { @@ -2424,28 +2413,28 @@ ], "support": { "issues": "https://github.com/markitosgv/JWTRefreshTokenBundle/issues", - "source": "https://github.com/markitosgv/JWTRefreshTokenBundle/tree/v1.3.0" + "source": "https://github.com/markitosgv/JWTRefreshTokenBundle/tree/v1.5.0" }, - "time": "2024-01-10T19:40:34+00:00" + "time": "2025-06-24T13:08:37+00:00" }, { "name": "guzzlehttp/guzzle", - "version": "7.9.2", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d281ed313b989f213357e3be1a179f02196ac99b", - "reference": "d281ed313b989f213357e3be1a179f02196ac99b", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0.3", - "guzzlehttp/psr7": "^2.7.0", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -2536,7 +2525,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.2" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -2552,20 +2541,20 @@ "type": "tidelift" } ], - "time": "2024-07-24T11:22:20+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.0.4", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", - "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -2573,7 +2562,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { @@ -2619,7 +2608,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.4" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -2635,20 +2624,20 @@ "type": "tidelift" } ], - "time": "2024-10-17T10:06:22+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.0", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/a70f5c95fb43bc83f07c9c948baa0dc1829bf201", - "reference": "a70f5c95fb43bc83f07c9c948baa0dc1829bf201", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -2664,7 +2653,7 @@ "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.39 || ^9.6.20" + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -2735,7 +2724,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.0" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -2751,24 +2740,24 @@ "type": "tidelift" } ], - "time": "2024-07-18T11:15:46+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "imagine/imagine", - "version": "1.3.5", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/php-imagine/Imagine.git", - "reference": "7151d553edec4dc2bbac60419f7a74ff34700e7f" + "reference": "80ab21434890dee9ba54969d31c51ac8d4d551e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/7151d553edec4dc2bbac60419f7a74ff34700e7f", - "reference": "7151d553edec4dc2bbac60419f7a74ff34700e7f", + "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/80ab21434890dee9ba54969d31c51ac8d4d551e0", + "reference": "80ab21434890dee9ba54969d31c51ac8d4d551e0", "shasum": "" }, "require": { - "php": ">=5.5" + "php": ">=7.1" }, "require-dev": { "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5 || ^8.4 || ^9.3" @@ -2801,7 +2790,7 @@ "homepage": "http://avalanche123.com" } ], - "description": "Image processing for PHP 5.3", + "description": "Image processing for PHP", "homepage": "http://imagine.readthedocs.org/", "keywords": [ "drawing", @@ -2811,9 +2800,9 @@ ], "support": { "issues": "https://github.com/php-imagine/Imagine/issues", - "source": "https://github.com/php-imagine/Imagine/tree/1.3.5" + "source": "https://github.com/php-imagine/Imagine/tree/1.5.0" }, - "time": "2023-06-07T14:49:52+00:00" + "time": "2024-12-03T14:37:55+00:00" }, { "name": "itk-dev/openid-connect", @@ -3072,26 +3061,26 @@ }, { "name": "kubawerlos/php-cs-fixer-custom-fixers", - "version": "v3.22.0", + "version": "v3.35.1", "source": { "type": "git", "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", - "reference": "8701394f0c7cd450ac4fa577d24589122c1d5d5e" + "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/8701394f0c7cd450ac4fa577d24589122c1d5d5e", - "reference": "8701394f0c7cd450ac4fa577d24589122c1d5d5e", + "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/2a35f80ae24ca77443a7af1599c3a3db1b6bd395", + "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395", "shasum": "" }, "require": { "ext-filter": "*", "ext-tokenizer": "*", - "friendsofphp/php-cs-fixer": "^3.61.1", + "friendsofphp/php-cs-fixer": "^3.87", "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.6.4 || ^10.5.29" + "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.32" }, "type": "library", "autoload": { @@ -3112,33 +3101,39 @@ "description": "A set of custom fixers for PHP CS Fixer", "support": { "issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues", - "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.22.0" + "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.35.1" }, - "time": "2024-08-16T20:44:35+00:00" + "funding": [ + { + "url": "https://github.com/kubawerlos", + "type": "github" + } + ], + "time": "2025-09-28T18:43:35+00:00" }, { "name": "laminas/laminas-code", - "version": "4.14.0", + "version": "4.17.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "562e02b7d85cb9142b5116cc76c4c7c162a11a1c" + "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/562e02b7d85cb9142b5116cc76c4c7c162a11a1c", - "reference": "562e02b7d85cb9142b5116cc76c4c7c162a11a1c", + "url": "https://api.github.com/repos/laminas/laminas-code/zipball/40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", + "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd", "shasum": "" }, "require": { - "php": "~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "doctrine/annotations": "^2.0.1", "ext-phar": "*", - "laminas/laminas-coding-standard": "^2.5.0", - "laminas/laminas-stdlib": "^3.17.0", - "phpunit/phpunit": "^10.3.3", + "laminas/laminas-coding-standard": "^3.0.0", + "laminas/laminas-stdlib": "^3.18.0", + "phpunit/phpunit": "^10.5.58", "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.15.0" }, @@ -3177,38 +3172,38 @@ "type": "community_bridge" } ], - "time": "2024-06-17T08:50:25+00:00" + "time": "2025-11-01T09:38:14+00:00" }, { "name": "lcobucci/clock", - "version": "3.3.1", + "version": "3.5.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b" + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/db3713a61addfffd615b79bf0bc22f0ccc61b86b", - "reference": "db3713a61addfffd615b79bf0bc22f0ccc61b86b", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/a3139d9e97d47826f27e6a17bb63f13621f86058", + "reference": "a3139d9e97d47826f27e6a17bb63f13621f86058", "shasum": "" }, "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "provide": { "psr/clock-implementation": "1.0" }, "require-dev": { - "infection/infection": "^0.29", - "lcobucci/coding-standard": "^11.1.0", + "infection/infection": "^0.31", + "lcobucci/coding-standard": "^11.2.0", "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.10.25", - "phpstan/phpstan-deprecation-rules": "^1.1.3", - "phpstan/phpstan-phpunit": "^1.3.13", - "phpstan/phpstan-strict-rules": "^1.5.1", - "phpunit/phpunit": "^11.3.6" + "phpstan/phpstan": "^2.0.0", + "phpstan/phpstan-deprecation-rules": "^2.0.0", + "phpstan/phpstan-phpunit": "^2.0.0", + "phpstan/phpstan-strict-rules": "^2.0.0", + "phpunit/phpunit": "^12.0.0" }, "type": "library", "autoload": { @@ -3229,7 +3224,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/3.3.1" + "source": "https://github.com/lcobucci/clock/tree/3.5.0" }, "funding": [ { @@ -3241,26 +3236,26 @@ "type": "patreon" } ], - "time": "2024-09-24T20:45:14+00:00" + "time": "2025-10-27T09:03:17+00:00" }, { "name": "lcobucci/jwt", - "version": "5.4.0", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051" + "reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/aac4fd512681fd5cb4b77d2105ab7ec700c72051", - "reference": "aac4fd512681fd5cb4b77d2105ab7ec700c72051", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/bb3e9f21e4196e8afc41def81ef649c164bca25e", + "reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e", "shasum": "" }, "require": { "ext-openssl": "*", "ext-sodium": "*", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", "psr/clock": "^1.0" }, "require-dev": { @@ -3302,7 +3297,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.4.0" + "source": "https://github.com/lcobucci/jwt/tree/5.6.0" }, "funding": [ { @@ -3314,39 +3309,34 @@ "type": "patreon" } ], - "time": "2024-10-08T22:06:45+00:00" + "time": "2025-10-17T11:30:53+00:00" }, { "name": "league/oauth2-client", - "version": "2.7.0", + "version": "2.8.1", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-client.git", - "reference": "160d6274b03562ebeb55ed18399281d8118b76c8" + "reference": "9df2924ca644736c835fc60466a3a60390d334f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/160d6274b03562ebeb55ed18399281d8118b76c8", - "reference": "160d6274b03562ebeb55ed18399281d8118b76c8", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/9df2924ca644736c835fc60466a3a60390d334f9", + "reference": "9df2924ca644736c835fc60466a3a60390d334f9", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "^6.0 || ^7.0", - "paragonie/random_compat": "^1 || ^2 || ^9.99", - "php": "^5.6 || ^7.0 || ^8.0" + "ext-json": "*", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", + "php": "^7.1 || >=8.0.0 <8.5.0" }, "require-dev": { "mockery/mockery": "^1.3.5", - "php-parallel-lint/php-parallel-lint": "^1.3.1", - "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5", - "squizlabs/php_codesniffer": "^2.3 || ^3.0" + "php-parallel-lint/php-parallel-lint": "^1.4", + "phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.11" }, "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.0.x-dev" - } - }, "autoload": { "psr-4": { "League\\OAuth2\\Client\\": "src/" @@ -3382,9 +3372,9 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-client/issues", - "source": "https://github.com/thephpleague/oauth2-client/tree/2.7.0" + "source": "https://github.com/thephpleague/oauth2-client/tree/2.8.1" }, - "time": "2023-04-16T18:19:15+00:00" + "time": "2025-02-26T04:37:30+00:00" }, { "name": "lexik/jwt-authentication-bundle", @@ -3507,22 +3497,23 @@ }, { "name": "liip/imagine-bundle", - "version": "2.13.2", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/liip/LiipImagineBundle.git", - "reference": "98e0318ea0f7b9500343236e63cc29ded58a1d43" + "reference": "f8c98a5a962806f26571db219412b64266c763d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/98e0318ea0f7b9500343236e63cc29ded58a1d43", - "reference": "98e0318ea0f7b9500343236e63cc29ded58a1d43", + "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/f8c98a5a962806f26571db219412b64266c763d8", + "reference": "f8c98a5a962806f26571db219412b64266c763d8", "shasum": "" }, "require": { "ext-mbstring": "*", "imagine/imagine": "^1.3.2", "php": "^7.2|^8.0", + "symfony/deprecation-contracts": "^2.5 || ^3", "symfony/filesystem": "^3.4|^4.4|^5.3|^6.0|^7.0", "symfony/finder": "^3.4|^4.4|^5.3|^6.0|^7.0", "symfony/framework-bundle": "^3.4.23|^4.4|^5.3|^6.0|^7.0", @@ -3607,22 +3598,22 @@ ], "support": { "issues": "https://github.com/liip/LiipImagineBundle/issues", - "source": "https://github.com/liip/LiipImagineBundle/tree/2.13.2" + "source": "https://github.com/liip/LiipImagineBundle/tree/2.15.0" }, - "time": "2024-09-04T12:55:26+00:00" + "time": "2025-10-09T06:49:28+00:00" }, { "name": "masterminds/html5", - "version": "2.9.0", + "version": "2.10.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + "reference": "fcf91eb64359852f00d921887b219479b4f21251" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", - "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251", + "reference": "fcf91eb64359852f00d921887b219479b4f21251", "shasum": "" }, "require": { @@ -3674,22 +3665,22 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + "source": "https://github.com/Masterminds/html5-php/tree/2.10.0" }, - "time": "2024-03-31T07:05:07+00:00" + "time": "2025-07-25T09:04:22+00:00" }, { "name": "monolog/monolog", - "version": "3.7.0", + "version": "3.9.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8" + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/10d85740180ecba7896c87e06a166e0c95a0e3b6", + "reference": "10d85740180ecba7896c87e06a166e0c95a0e3b6", "shasum": "" }, "require": { @@ -3709,12 +3700,14 @@ "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.5.17", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -3765,7 +3758,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.7.0" + "source": "https://github.com/Seldaek/monolog/tree/3.9.0" }, "funding": [ { @@ -3777,7 +3770,7 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:40:51+00:00" + "time": "2025-03-24T10:02:05+00:00" }, { "name": "namshi/jose", @@ -3848,25 +3841,28 @@ }, { "name": "nelmio/cors-bundle", - "version": "2.5.0", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioCorsBundle.git", - "reference": "3a526fe025cd20e04a6a11370cf5ab28dbb5a544" + "reference": "530217472204881cacd3671909f634b960c7b948" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/3a526fe025cd20e04a6a11370cf5ab28dbb5a544", - "reference": "3a526fe025cd20e04a6a11370cf5ab28dbb5a544", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/530217472204881cacd3671909f634b960c7b948", + "reference": "530217472204881cacd3671909f634b960c7b948", "shasum": "" }, "require": { "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0" + "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { - "mockery/mockery": "^1.3.6", - "symfony/phpunit-bridge": "^5.4 || ^6.0 || ^7.0" + "phpstan/phpstan": "^1.11.5", + "phpstan/phpstan-deprecation-rules": "^1.2.0", + "phpstan/phpstan-phpunit": "^1.4", + "phpstan/phpstan-symfony": "^1.4.4", + "phpunit/phpunit": "^8" }, "type": "symfony-bundle", "extra": { @@ -3904,9 +3900,9 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", - "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.5.0" + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.6.0" }, - "time": "2024-06-24T21:25:28+00:00" + "time": "2025-10-23T06:57:22+00:00" }, { "name": "nyholm/psr7", @@ -3986,56 +3982,6 @@ ], "time": "2024-09-09T07:06:30+00:00" }, - { - "name": "paragonie/random_compat", - "version": "v9.99.100", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", - "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", - "shasum": "" - }, - "require": { - "php": ">= 7" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*", - "vimeo/psalm": "^1" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "polyfill", - "pseudorandom", - "random" - ], - "support": { - "email": "info@paragonie.com", - "issues": "https://github.com/paragonie/random_compat/issues", - "source": "https://github.com/paragonie/random_compat" - }, - "time": "2020-10-15T08:29:30+00:00" - }, { "name": "php-http/discovery", "version": "1.20.0", @@ -4279,16 +4225,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", + "version": "5.6.4", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90a04bcbf03784066f16038e87e23a0a83cee3c2", + "reference": "90a04bcbf03784066f16038e87e23a0a83cee3c2", "shasum": "" }, "require": { @@ -4297,17 +4243,17 @@ "php": "^7.4 || ^8.0", "phpdocumentor/reflection-common": "^2.2", "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", + "phpstan/phpdoc-parser": "^1.7|^2.0", "webmozart/assert": "^1.9.1" }, "require-dev": { - "mockery/mockery": "~1.3.5", + "mockery/mockery": "~1.3.5 || ~1.6.0", "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.8", "phpstan/phpstan-mockery": "^1.1", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" + "psalm/phar": "^5.26" }, "type": "library", "extra": { @@ -4337,29 +4283,29 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.4" }, - "time": "2024-05-21T05:55:05+00:00" + "time": "2025-11-17T21:13:10+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.8.2", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "153ae662783729388a584b4361f2545e4d841e3c" + "reference": "f626740b38009078de0dc8b2b9dc4e7f749c6eba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", - "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/f626740b38009078de0dc8b2b9dc4e7f749c6eba", + "reference": "f626740b38009078de0dc8b2b9dc4e7f749c6eba", "shasum": "" }, "require": { "doctrine/deprecations": "^1.0", "php": "^7.3 || ^8.0", "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.13" + "phpstan/phpdoc-parser": "^1.18|^2.0" }, "require-dev": { "ext-tokenizer": "*", @@ -4395,9 +4341,9 @@ "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", "support": { "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.11.1" }, - "time": "2024-02-23T11:10:43+00:00" + "time": "2025-11-21T11:31:57+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -5030,33 +4976,33 @@ }, { "name": "react/child-process", - "version": "v0.6.5", + "version": "v0.6.6", "source": { "type": "git", "url": "https://github.com/reactphp/child-process.git", - "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43" + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/child-process/zipball/e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", - "reference": "e71eb1aa55f057c7a4a0d08d06b0b0a484bead43", + "url": "https://api.github.com/repos/reactphp/child-process/zipball/1721e2b93d89b745664353b9cfc8f155ba8a6159", + "reference": "1721e2b93d89b745664353b9cfc8f155ba8a6159", "shasum": "" }, "require": { "evenement/evenement": "^3.0 || ^2.0 || ^1.0", "php": ">=5.3.0", "react/event-loop": "^1.2", - "react/stream": "^1.2" + "react/stream": "^1.4" }, "require-dev": { - "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35", - "react/socket": "^1.8", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/socket": "^1.16", "sebastian/environment": "^5.0 || ^3.0 || ^2.0 || ^1.0" }, "type": "library", "autoload": { "psr-4": { - "React\\ChildProcess\\": "src" + "React\\ChildProcess\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5093,32 +5039,28 @@ ], "support": { "issues": "https://github.com/reactphp/child-process/issues", - "source": "https://github.com/reactphp/child-process/tree/v0.6.5" + "source": "https://github.com/reactphp/child-process/tree/v0.6.6" }, "funding": [ { - "url": "https://github.com/WyriHaximus", - "type": "github" - }, - { - "url": "https://github.com/clue", - "type": "github" + "url": "https://opencollective.com/reactphp", + "type": "open_collective" } ], - "time": "2022-09-16T13:41:56+00:00" + "time": "2025-01-01T16:37:48+00:00" }, { "name": "react/dns", - "version": "v1.13.0", + "version": "v1.14.0", "source": { "type": "git", "url": "https://github.com/reactphp/dns.git", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5" + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", - "reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5", + "url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3", + "reference": "7562c05391f42701c1fccf189c8225fece1cd7c3", "shasum": "" }, "require": { @@ -5173,7 +5115,7 @@ ], "support": { "issues": "https://github.com/reactphp/dns/issues", - "source": "https://github.com/reactphp/dns/tree/v1.13.0" + "source": "https://github.com/reactphp/dns/tree/v1.14.0" }, "funding": [ { @@ -5181,20 +5123,20 @@ "type": "open_collective" } ], - "time": "2024-06-13T14:18:03+00:00" + "time": "2025-11-18T19:34:28+00:00" }, { "name": "react/event-loop", - "version": "v1.5.0", + "version": "v1.6.0", "source": { "type": "git", "url": "https://github.com/reactphp/event-loop.git", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", - "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a", + "reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a", "shasum": "" }, "require": { @@ -5245,7 +5187,7 @@ ], "support": { "issues": "https://github.com/reactphp/event-loop/issues", - "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + "source": "https://github.com/reactphp/event-loop/tree/v1.6.0" }, "funding": [ { @@ -5253,27 +5195,27 @@ "type": "open_collective" } ], - "time": "2023-11-13T13:48:05+00:00" + "time": "2025-11-17T20:46:25+00:00" }, { "name": "react/promise", - "version": "v3.2.0", + "version": "v3.3.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63" + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/8a164643313c71354582dc850b42b33fa12a4b63", - "reference": "8a164643313c71354582dc850b42b33fa12a4b63", + "url": "https://api.github.com/repos/reactphp/promise/zipball/23444f53a813a3296c1368bb104793ce8d88f04a", + "reference": "23444f53a813a3296c1368bb104793ce8d88f04a", "shasum": "" }, "require": { "php": ">=7.1.0" }, "require-dev": { - "phpstan/phpstan": "1.10.39 || 1.4.10", + "phpstan/phpstan": "1.12.28 || 1.4.10", "phpunit/phpunit": "^9.6 || ^7.5" }, "type": "library", @@ -5318,7 +5260,7 @@ ], "support": { "issues": "https://github.com/reactphp/promise/issues", - "source": "https://github.com/reactphp/promise/tree/v3.2.0" + "source": "https://github.com/reactphp/promise/tree/v3.3.0" }, "funding": [ { @@ -5326,20 +5268,20 @@ "type": "open_collective" } ], - "time": "2024-05-24T10:39:05+00:00" + "time": "2025-08-19T18:57:03+00:00" }, { "name": "react/socket", - "version": "v1.16.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/reactphp/socket.git", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1" + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", - "reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1", + "url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08", + "reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08", "shasum": "" }, "require": { @@ -5398,7 +5340,7 @@ ], "support": { "issues": "https://github.com/reactphp/socket/issues", - "source": "https://github.com/reactphp/socket/tree/v1.16.0" + "source": "https://github.com/reactphp/socket/tree/v1.17.0" }, "funding": [ { @@ -5406,7 +5348,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -5488,16 +5430,16 @@ }, { "name": "rlanvin/php-rrule", - "version": "v2.5.1", + "version": "v2.6.0", "source": { "type": "git", "url": "https://github.com/rlanvin/php-rrule.git", - "reference": "cb5c6f44f2208144968f7f16b3461bc4566995c9" + "reference": "2a389a9fa67dda58bc5a569a3264555152db3c49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rlanvin/php-rrule/zipball/cb5c6f44f2208144968f7f16b3461bc4566995c9", - "reference": "cb5c6f44f2208144968f7f16b3461bc4566995c9", + "url": "https://api.github.com/repos/rlanvin/php-rrule/zipball/2a389a9fa67dda58bc5a569a3264555152db3c49", + "reference": "2a389a9fa67dda58bc5a569a3264555152db3c49", "shasum": "" }, "require": { @@ -5531,22 +5473,22 @@ ], "support": { "issues": "https://github.com/rlanvin/php-rrule/issues", - "source": "https://github.com/rlanvin/php-rrule/tree/v2.5.1" + "source": "https://github.com/rlanvin/php-rrule/tree/v2.6.0" }, - "time": "2024-06-23T07:45:45+00:00" + "time": "2025-04-25T07:40:09+00:00" }, { "name": "robrichards/xmlseclibs", - "version": "3.1.1", + "version": "3.1.3", "source": { "type": "git", "url": "https://github.com/robrichards/xmlseclibs.git", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df" + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/f8f19e58f26cdb42c54b214ff8a820760292f8df", - "reference": "f8f19e58f26cdb42c54b214ff8a820760292f8df", + "url": "https://api.github.com/repos/robrichards/xmlseclibs/zipball/2bdfd742624d739dfadbd415f00181b4a77aaf07", + "reference": "2bdfd742624d739dfadbd415f00181b4a77aaf07", "shasum": "" }, "require": { @@ -5573,9 +5515,9 @@ ], "support": { "issues": "https://github.com/robrichards/xmlseclibs/issues", - "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.1" + "source": "https://github.com/robrichards/xmlseclibs/tree/3.1.3" }, - "time": "2020-09-05T13:00:25+00:00" + "time": "2024-11-20T21:13:56+00:00" }, { "name": "sebastian/diff", @@ -5645,16 +5587,16 @@ }, { "name": "symfony/asset", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "c668aa320e26b7379540368832b9d1dd43d32603" + "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/c668aa320e26b7379540368832b9d1dd43d32603", - "reference": "c668aa320e26b7379540368832b9d1dd43d32603", + "url": "https://api.github.com/repos/symfony/asset/zipball/cfee7c0d64be113383db74a2fdd65d426b7f3aab", + "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab", "shasum": "" }, "require": { @@ -5694,7 +5636,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v6.4.8" + "source": "https://github.com/symfony/asset/tree/v6.4.24" }, "funding": [ { @@ -5705,25 +5647,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/cache", - "version": "v6.4.12", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8" + "reference": "31628f36fc97c5714d181b3a8d29efb85c6a7677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a463451b7f6ac4a47b98dbfc78ec2d3560c759d8", - "reference": "a463451b7f6ac4a47b98dbfc78ec2d3560c759d8", + "url": "https://api.github.com/repos/symfony/cache/zipball/31628f36fc97c5714d181b3a8d29efb85c6a7677", + "reference": "31628f36fc97c5714d181b3a8d29efb85c6a7677", "shasum": "" }, "require": { @@ -5790,7 +5736,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.12" + "source": "https://github.com/symfony/cache/tree/v6.4.28" }, "funding": [ { @@ -5801,25 +5747,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-16T16:01:33+00:00" + "time": "2025-10-30T08:37:02+00:00" }, { "name": "symfony/cache-contracts", - "version": "v3.5.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/cache-contracts.git", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197" + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/df6a1a44c890faded49a5fca33c2d5c5fd3c2197", - "reference": "df6a1a44c890faded49a5fca33c2d5c5fd3c2197", + "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/5d68a57d66910405e5c0b63d6f0af941e66fc868", + "reference": "5d68a57d66910405e5c0b63d6f0af941e66fc868", "shasum": "" }, "require": { @@ -5828,12 +5778,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -5866,7 +5816,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/cache-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/cache-contracts/tree/v3.6.0" }, "funding": [ { @@ -5882,20 +5832,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-03-13T15:25:07+00:00" }, { "name": "symfony/clock", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "7a4840efd17135cbd547e41ec49fb910ed4f8b98" + "reference": "5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/7a4840efd17135cbd547e41ec49fb910ed4f8b98", - "reference": "7a4840efd17135cbd547e41ec49fb910ed4f8b98", + "url": "https://api.github.com/repos/symfony/clock/zipball/5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8", + "reference": "5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8", "shasum": "" }, "require": { @@ -5940,7 +5890,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v6.4.8" + "source": "https://github.com/symfony/clock/tree/v6.4.24" }, "funding": [ { @@ -5951,25 +5901,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:51:39+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/config", - "version": "v6.4.8", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35" + "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/12e7e52515ce37191b193cf3365903c4f3951e35", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35", + "url": "https://api.github.com/repos/symfony/config/zipball/15947c18ef3ddb0b2f4ec936b9e90e2520979f62", + "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62", "shasum": "" }, "require": { @@ -6015,7 +5969,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.8" + "source": "https://github.com/symfony/config/tree/v6.4.28" }, "funding": [ { @@ -6026,25 +5980,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-11-01T19:52:02+00:00" }, { "name": "symfony/console", - "version": "v6.4.12", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765" + "reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/72d080eb9edf80e36c19be61f72c98ed8273b765", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765", + "url": "https://api.github.com/repos/symfony/console/zipball/13d3176cf8ad8ced24202844e9f95af11e2959fc", + "reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc", "shasum": "" }, "require": { @@ -6109,7 +6067,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.12" + "source": "https://github.com/symfony/console/tree/v6.4.27" }, "funding": [ { @@ -6120,25 +6078,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2025-10-06T10:25:16+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "cfb9d34a1cdd4911bc737a5358fd1cf8ebfb536e" + "reference": "5f311eaf0b321f8ec640f6bae12da43a14026898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/cfb9d34a1cdd4911bc737a5358fd1cf8ebfb536e", - "reference": "cfb9d34a1cdd4911bc737a5358fd1cf8ebfb536e", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5f311eaf0b321f8ec640f6bae12da43a14026898", + "reference": "5f311eaf0b321f8ec640f6bae12da43a14026898", "shasum": "" }, "require": { @@ -6146,7 +6108,7 @@ "psr/container": "^1.1|^2.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/service-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^6.2.10|^7.0" + "symfony/var-exporter": "^6.4.20|^7.2.5" }, "conflict": { "ext-psr": "<1.1|>=2", @@ -6190,7 +6152,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.12" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.26" }, "funding": [ { @@ -6201,25 +6163,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:18:25+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -6227,12 +6193,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -6257,7 +6223,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -6273,25 +6239,25 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "b5c0a0172bbe9b1435181d94ca5cbe4af3fb45af" + "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/b5c0a0172bbe9b1435181d94ca5cbe4af3fb45af", - "reference": "b5c0a0172bbe9b1435181d94ca5cbe4af3fb45af", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/c14bb5a9125c411e73354954940e06b6e7fcc344", + "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344", "shasum": "" }, "require": { "doctrine/event-manager": "^1.2|^2", - "doctrine/persistence": "^3.1", + "doctrine/persistence": "^2.5|^3.1|^4", "php": ">=8.1", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", @@ -6316,7 +6282,7 @@ }, "require-dev": { "doctrine/collections": "^1.0|^2.0", - "doctrine/data-fixtures": "^1.1", + "doctrine/data-fixtures": "^1.1|^2", "doctrine/dbal": "^2.13.1|^3|^4", "doctrine/orm": "^2.15|^3", "psr/log": "^1|^2|^3", @@ -6365,7 +6331,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.12" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.26" }, "funding": [ { @@ -6376,25 +6342,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-08T12:31:10+00:00" + "time": "2025-09-26T15:07:38+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.4.13", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "ae074dffb018c37a57071990d16e6152728dd972" + "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ae074dffb018c37a57071990d16e6152728dd972", - "reference": "ae074dffb018c37a57071990d16e6152728dd972", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/976302990f9f2a6d4c07206836dd4ca77cae9524", + "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524", "shasum": "" }, "require": { @@ -6432,7 +6402,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.13" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.25" }, "funding": [ { @@ -6443,25 +6413,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-25T15:07:50+00:00" + "time": "2025-08-05T18:56:08+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.12", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "815284236cab7d8e1280f53bf562c07a4dfe5954" + "reference": "234b6c602f12b00693f4b0d1054386fb30dfc8ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/815284236cab7d8e1280f53bf562c07a4dfe5954", - "reference": "815284236cab7d8e1280f53bf562c07a4dfe5954", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/234b6c602f12b00693f4b0d1054386fb30dfc8ff", + "reference": "234b6c602f12b00693f4b0d1054386fb30dfc8ff", "shasum": "" }, "require": { @@ -6506,7 +6480,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.12" + "source": "https://github.com/symfony/dotenv/tree/v6.4.24" }, "funding": [ { @@ -6517,25 +6491,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-16T16:01:33+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.10", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0" + "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/231f1b2ee80f72daa1972f7340297d67439224f0", - "reference": "231f1b2ee80f72daa1972f7340297d67439224f0", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/41bedcaec5b72640b0ec2096547b75fda72ead6c", + "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c", "shasum": "" }, "require": { @@ -6581,7 +6559,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.10" + "source": "https://github.com/symfony/error-handler/tree/v6.4.26" }, "funding": [ { @@ -6592,25 +6570,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T12:30:32+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.8", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b" + "reference": "b0cf3162020603587363f0551cd3be43958611ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/8d7507f02b06e06815e56bb39aa0128e3806208b", - "reference": "8d7507f02b06e06815e56bb39aa0128e3806208b", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b0cf3162020603587363f0551cd3be43958611ff", + "reference": "b0cf3162020603587363f0551cd3be43958611ff", "shasum": "" }, "require": { @@ -6661,7 +6643,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.25" }, "funding": [ { @@ -6672,25 +6654,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-08-13T09:41:44+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "59eb412e93815df44f05f342958efa9f46b1e586" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/59eb412e93815df44f05f342958efa9f46b1e586", + "reference": "59eb412e93815df44f05f342958efa9f46b1e586", "shasum": "" }, "require": { @@ -6699,12 +6685,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -6737,7 +6723,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.6.0" }, "funding": [ { @@ -6753,20 +6739,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/expression-language", - "version": "v6.4.11", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "564e109c40d3637053c942a29a58e9434592a8bf" + "reference": "1ea0adaa53539ea7e70821ae9de49ebe03ae7091" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/564e109c40d3637053c942a29a58e9434592a8bf", - "reference": "564e109c40d3637053c942a29a58e9434592a8bf", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/1ea0adaa53539ea7e70821ae9de49ebe03ae7091", + "reference": "1ea0adaa53539ea7e70821ae9de49ebe03ae7091", "shasum": "" }, "require": { @@ -6801,7 +6787,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v6.4.11" + "source": "https://github.com/symfony/expression-language/tree/v6.4.24" }, "funding": [ { @@ -6812,25 +6798,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.12", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "f810e3cbdf7fdc35983968523d09f349fa9ada12" + "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/f810e3cbdf7fdc35983968523d09f349fa9ada12", - "reference": "f810e3cbdf7fdc35983968523d09f349fa9ada12", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", + "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", "shasum": "" }, "require": { @@ -6867,7 +6857,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.12" + "source": "https://github.com/symfony/filesystem/tree/v6.4.24" }, "funding": [ { @@ -6878,25 +6868,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-16T16:01:33+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/finder", - "version": "v6.4.11", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453" + "reference": "a1b6aa435d2fba50793b994a839c32b6064f063b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d7eb6daf8cd7e9ac4976e9576b32042ef7253453", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453", + "url": "https://api.github.com/repos/symfony/finder/zipball/a1b6aa435d2fba50793b994a839c32b6064f063b", + "reference": "a1b6aa435d2fba50793b994a839c32b6064f063b", "shasum": "" }, "require": { @@ -6931,7 +6925,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.11" + "source": "https://github.com/symfony/finder/tree/v6.4.27" }, "funding": [ { @@ -6942,40 +6936,45 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-13T14:27:37+00:00" + "time": "2025-10-15T18:32:00+00:00" }, { "name": "symfony/flex", - "version": "v2.4.7", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "92f4fba342161ff36072bd3b8e0b3c6c23160402" + "reference": "9cd384775973eabbf6e8b05784dda279fc67c28d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/92f4fba342161ff36072bd3b8e0b3c6c23160402", - "reference": "92f4fba342161ff36072bd3b8e0b3c6c23160402", + "url": "https://api.github.com/repos/symfony/flex/zipball/9cd384775973eabbf6e8b05784dda279fc67c28d", + "reference": "9cd384775973eabbf6e8b05784dda279fc67c28d", "shasum": "" }, "require": { "composer-plugin-api": "^2.1", - "php": ">=8.0" + "php": ">=8.1" }, "conflict": { - "composer/semver": "<1.7.2" + "composer/semver": "<1.7.2", + "symfony/dotenv": "<5.4" }, "require-dev": { "composer/composer": "^2.1", - "symfony/dotenv": "^5.4|^6.0", - "symfony/filesystem": "^5.4|^6.0", - "symfony/phpunit-bridge": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0" + "symfony/dotenv": "^6.4|^7.4|^8.0", + "symfony/filesystem": "^6.4|^7.4|^8.0", + "symfony/phpunit-bridge": "^6.4|^7.4|^8.0", + "symfony/process": "^6.4|^7.4|^8.0" }, "type": "composer-plugin", "extra": { @@ -6999,7 +6998,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.4.7" + "source": "https://github.com/symfony/flex/tree/v2.10.0" }, "funding": [ { @@ -7010,25 +7009,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-10-07T08:51:54+00:00" + "time": "2025-11-16T09:38:19+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.12", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "6a9665bd1fae37b198429775c6132f193339434f" + "reference": "ee58c2a73218d8f4763824e1414c5f9b4519c91f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/6a9665bd1fae37b198429775c6132f193339434f", - "reference": "6a9665bd1fae37b198429775c6132f193339434f", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ee58c2a73218d8f4763824e1414c5f9b4519c91f", + "reference": "ee58c2a73218d8f4763824e1414c5f9b4519c91f", "shasum": "" }, "require": { @@ -7067,6 +7070,7 @@ "symfony/mime": "<6.4", "symfony/property-access": "<5.4", "symfony/property-info": "<5.4", + "symfony/runtime": "<5.4.45|>=6.0,<6.4.13|>=7.0,<7.1.6", "symfony/scheduler": "<6.4.4|>=7.0.0,<7.0.4", "symfony/security-core": "<5.4", "symfony/security-csrf": "<5.4", @@ -7147,7 +7151,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.12" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.27" }, "funding": [ { @@ -7158,32 +7162,37 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T13:34:56+00:00" + "time": "2025-10-15T17:35:09+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.12", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56" + "reference": "c9e69c185c4a845f9d46958cdb0dc7aa847f3981" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", - "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c9e69c185c4a845f9d46958cdb0dc7aa847f3981", + "reference": "c9e69c185c4a845f9d46958cdb0dc7aa847f3981", "shasum": "" }, "require": { "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", + "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/polyfill-php83": "^1.29", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -7240,7 +7249,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.12" + "source": "https://github.com/symfony/http-client/tree/v6.4.28" }, "funding": [ { @@ -7251,25 +7260,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:21:33+00:00" + "time": "2025-11-05T17:39:22+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.5.0", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -7277,12 +7290,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -7318,7 +7331,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -7334,20 +7347,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.4.12", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "133ac043875f59c26c55e79cf074562127cce4d2" + "reference": "b03d11e015552a315714c127d8d1e0f9e970ec88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/133ac043875f59c26c55e79cf074562127cce4d2", - "reference": "133ac043875f59c26c55e79cf074562127cce4d2", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b03d11e015552a315714c127d8d1e0f9e970ec88", + "reference": "b03d11e015552a315714c127d8d1e0f9e970ec88", "shasum": "" }, "require": { @@ -7357,12 +7370,12 @@ "symfony/polyfill-php83": "^1.27" }, "conflict": { - "symfony/cache": "<6.3" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^2.13.1|^3|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.3|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4|^7.0", @@ -7395,7 +7408,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.12" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.29" }, "funding": [ { @@ -7406,25 +7419,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:18:25+00:00" + "time": "2025-11-08T16:40:12+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.12", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "96df83d51b5f78804f70c093b97310794fd6257b" + "reference": "18818b48f54c1d2bd92b41d82d8345af50b15658" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/96df83d51b5f78804f70c093b97310794fd6257b", - "reference": "96df83d51b5f78804f70c093b97310794fd6257b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/18818b48f54c1d2bd92b41d82d8345af50b15658", + "reference": "18818b48f54c1d2bd92b41d82d8345af50b15658", "shasum": "" }, "require": { @@ -7509,7 +7526,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.12" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.29" }, "funding": [ { @@ -7521,24 +7538,28 @@ "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "time": "2024-09-21T06:02:57+00:00" + "time": "2025-11-12T11:22:59+00:00" }, { "name": "symfony/mime", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "abe16ee7790b16aa525877419deb0f113953f0e1" + "reference": "61ab9681cdfe315071eb4fa79b6ad6ab030a9235" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/abe16ee7790b16aa525877419deb0f113953f0e1", - "reference": "abe16ee7790b16aa525877419deb0f113953f0e1", + "url": "https://api.github.com/repos/symfony/mime/zipball/61ab9681cdfe315071eb4fa79b6ad6ab030a9235", + "reference": "61ab9681cdfe315071eb4fa79b6ad6ab030a9235", "shasum": "" }, "require": { @@ -7594,7 +7615,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.12" + "source": "https://github.com/symfony/mime/tree/v6.4.26" }, "funding": [ { @@ -7605,25 +7626,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:18:25+00:00" + "time": "2025-09-16T08:22:30+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v6.4.8", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "0fbee64913b1c595e7650a1919ba3edba8d49ea7" + "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/0fbee64913b1c595e7650a1919ba3edba8d49ea7", - "reference": "0fbee64913b1c595e7650a1919ba3edba8d49ea7", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/d2f4b68e3247cf44d93f48545c8c072a75c17e5b", + "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b", "shasum": "" }, "require": { @@ -7673,7 +7698,7 @@ "description": "Provides integration for Monolog with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.8" + "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.28" }, "funding": [ { @@ -7684,12 +7709,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-10-30T19:57:08+00:00" }, { "name": "symfony/monolog-bundle", @@ -7774,16 +7803,16 @@ }, { "name": "symfony/options-resolver", - "version": "v6.4.8", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b" + "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/22ab9e9101ab18de37839074f8a1197f55590c1b", - "reference": "22ab9e9101ab18de37839074f8a1197f55590c1b", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28e7e2db8a73e9511df892d36445f61314bbebe", + "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe", "shasum": "" }, "require": { @@ -7821,7 +7850,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.8" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.25" }, "funding": [ { @@ -7832,25 +7861,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-08-04T17:06:28+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31" + "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/90ebbe946e5d64a5fad9ac9427e335045cf2bd31", - "reference": "90ebbe946e5d64a5fad9ac9427e335045cf2bd31", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/dcab5ac87450aaed26483ba49c2ce86808da7557", + "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557", "shasum": "" }, "require": { @@ -7893,7 +7926,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.8" + "source": "https://github.com/symfony/password-hasher/tree/v6.4.24" }, "funding": [ { @@ -7904,25 +7937,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", - "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", "shasum": "" }, "require": { @@ -7934,8 +7971,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -7971,7 +8008,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -7982,25 +8019,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773" + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/c36586dcf89a12315939e00ec9b4474adcb1d773", - "reference": "c36586dcf89a12315939e00ec9b4474adcb1d773", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", "shasum": "" }, "require": { @@ -8013,8 +8054,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8054,7 +8095,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -8065,16 +8106,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-09-10T14:38:51+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -8095,8 +8140,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8135,7 +8180,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -8146,6 +8191,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -8155,19 +8204,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -8179,8 +8229,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8215,7 +8265,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -8226,12 +8276,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/polyfill-php56", @@ -8252,12 +8306,12 @@ }, "type": "metapackage", "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + }, "branch-alias": { "dev-main": "1.20-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" } }, "notification-url": "https://packagist.org/downloads/", @@ -8303,16 +8357,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", - "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { @@ -8321,8 +8375,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8363,7 +8417,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -8374,16 +8428,20 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -8401,8 +8459,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8439,7 +8497,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -8450,6 +8508,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -8459,16 +8521,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", - "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5", + "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5", "shasum": "" }, "require": { @@ -8477,8 +8539,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8515,7 +8577,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -8526,16 +8588,100 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2025-07-08T02:45:35+00:00" + }, + { + "name": "symfony/polyfill-php84", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php84.git", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php84\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-24T13:30:11+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.31.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -8559,8 +8705,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -8594,7 +8740,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" }, "funding": [ { @@ -8605,6 +8751,10 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" @@ -8614,16 +8764,16 @@ }, { "name": "symfony/process", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "3f94e5f13ff58df371a7ead461b6e8068900fbb3" + "reference": "48bad913268c8cafabbf7034b39c8bb24fbc5ab8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/3f94e5f13ff58df371a7ead461b6e8068900fbb3", - "reference": "3f94e5f13ff58df371a7ead461b6e8068900fbb3", + "url": "https://api.github.com/repos/symfony/process/zipball/48bad913268c8cafabbf7034b39c8bb24fbc5ab8", + "reference": "48bad913268c8cafabbf7034b39c8bb24fbc5ab8", "shasum": "" }, "require": { @@ -8655,7 +8805,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.12" + "source": "https://github.com/symfony/process/tree/v6.4.26" }, "funding": [ { @@ -8666,25 +8816,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-17T12:47:12+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/property-access", - "version": "v6.4.11", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "866f6cd84f2094cbc6f66ce9752faf749916e2a9" + "reference": "fedc771326d4978a7d3167fa009a509b06a2e168" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/866f6cd84f2094cbc6f66ce9752faf749916e2a9", - "reference": "866f6cd84f2094cbc6f66ce9752faf749916e2a9", + "url": "https://api.github.com/repos/symfony/property-access/zipball/fedc771326d4978a7d3167fa009a509b06a2e168", + "reference": "fedc771326d4978a7d3167fa009a509b06a2e168", "shasum": "" }, "require": { @@ -8732,7 +8886,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.4.11" + "source": "https://github.com/symfony/property-access/tree/v6.4.25" }, "funding": [ { @@ -8743,25 +8897,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-30T16:10:11+00:00" + "time": "2025-08-12T15:42:57+00:00" }, { "name": "symfony/property-info", - "version": "v6.4.10", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77" + "reference": "1056ae3621eeddd78d7c5ec074f1c1784324eec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", - "reference": "edaea9dcc723cb4a0ab6a00f7d6f8c07c0d8ff77", + "url": "https://api.github.com/repos/symfony/property-info/zipball/1056ae3621eeddd78d7c5ec074f1c1784324eec6", + "reference": "1056ae3621eeddd78d7c5ec074f1c1784324eec6", "shasum": "" }, "require": { @@ -8769,17 +8927,20 @@ "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { + "doctrine/annotations": "<1.12", "phpdocumentor/reflection-docblock": "<5.2", "phpdocumentor/type-resolver": "<1.5.1", - "symfony/dependency-injection": "<5.4", - "symfony/serializer": "<6.4" + "symfony/cache": "<5.4", + "symfony/dependency-injection": "<5.4|>=6.0,<6.4", + "symfony/serializer": "<5.4" }, "require-dev": { + "doctrine/annotations": "^1.12|^2", "phpdocumentor/reflection-docblock": "^5.2", - "phpstan/phpdoc-parser": "^1.0", + "phpstan/phpdoc-parser": "^1.0|^2.0", "symfony/cache": "^5.4|^6.0|^7.0", "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/serializer": "^6.4|^7.0" + "symfony/serializer": "^5.4|^6.4|^7.0" }, "type": "library", "autoload": { @@ -8815,7 +8976,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.10" + "source": "https://github.com/symfony/property-info/tree/v6.4.24" }, "funding": [ { @@ -8826,25 +8987,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-07-26T07:32:07+00:00" + "time": "2025-07-14T16:38:25+00:00" }, { "name": "symfony/proxy-manager-bridge", - "version": "v6.4.8", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", - "reference": "b8119e0b248ef0711c25cd09acc729102122621c" + "reference": "9ecac7f98ad685d474394dbd06dab29bab4e18a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/b8119e0b248ef0711c25cd09acc729102122621c", - "reference": "b8119e0b248ef0711c25cd09acc729102122621c", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/9ecac7f98ad685d474394dbd06dab29bab4e18a6", + "reference": "9ecac7f98ad685d474394dbd06dab29bab4e18a6", "shasum": "" }, "require": { @@ -8882,7 +9047,7 @@ "description": "Provides integration for ProxyManager with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.8" + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.28" }, "funding": [ { @@ -8893,25 +9058,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-11-02T18:11:54+00:00" }, { "name": "symfony/routing", - "version": "v6.4.12", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "a7c8036bd159486228dc9be3e846a00a0dda9f9f" + "reference": "ae064a6d9cf39507f9797658465a2ca702965fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/a7c8036bd159486228dc9be3e846a00a0dda9f9f", - "reference": "a7c8036bd159486228dc9be3e846a00a0dda9f9f", + "url": "https://api.github.com/repos/symfony/routing/zipball/ae064a6d9cf39507f9797658465a2ca702965fa8", + "reference": "ae064a6d9cf39507f9797658465a2ca702965fa8", "shasum": "" }, "require": { @@ -8965,7 +9134,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.12" + "source": "https://github.com/symfony/routing/tree/v6.4.28" }, "funding": [ { @@ -8976,25 +9145,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:32:26+00:00" + "time": "2025-10-31T16:43:05+00:00" }, { "name": "symfony/runtime", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "bfe32a1adf41da4dd7f6b939a039779d7af5497f" + "reference": "59933ca737fd60fad548241b6d879cd0e4be31ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/bfe32a1adf41da4dd7f6b939a039779d7af5497f", - "reference": "bfe32a1adf41da4dd7f6b939a039779d7af5497f", + "url": "https://api.github.com/repos/symfony/runtime/zipball/59933ca737fd60fad548241b6d879cd0e4be31ab", + "reference": "59933ca737fd60fad548241b6d879cd0e4be31ab", "shasum": "" }, "require": { @@ -9044,7 +9217,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.12" + "source": "https://github.com/symfony/runtime/tree/v6.4.26" }, "funding": [ { @@ -9055,25 +9228,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-19T13:29:10+00:00" + "time": "2025-09-11T15:30:54+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.4.11", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "620be16fceded671823ce6332d06f44bb327096d" + "reference": "b83773107a5b83a5507df9e88bd50d495f6e8b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/620be16fceded671823ce6332d06f44bb327096d", - "reference": "620be16fceded671823ce6332d06f44bb327096d", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/b83773107a5b83a5507df9e88bd50d495f6e8b72", + "reference": "b83773107a5b83a5507df9e88bd50d495f6e8b72", "shasum": "" }, "require": { @@ -9156,7 +9333,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.11" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.26" }, "funding": [ { @@ -9167,25 +9344,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-20T11:22:16+00:00" + "time": "2025-09-22T15:03:07+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.12", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "8c7e52155262b3ef6b7885f6d9bd90fb24eaa66f" + "reference": "673018434b38e504eb04ca3c6d7e2e7c86735bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/8c7e52155262b3ef6b7885f6d9bd90fb24eaa66f", - "reference": "8c7e52155262b3ef6b7885f6d9bd90fb24eaa66f", + "url": "https://api.github.com/repos/symfony/security-core/zipball/673018434b38e504eb04ca3c6d7e2e7c86735bfb", + "reference": "673018434b38e504eb04ca3c6d7e2e7c86735bfb", "shasum": "" }, "require": { @@ -9242,7 +9423,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.12" + "source": "https://github.com/symfony/security-core/tree/v6.4.27" }, "funding": [ { @@ -9253,25 +9434,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:21:33+00:00" + "time": "2025-10-23T19:49:35+00:00" }, { "name": "symfony/security-csrf", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "f46ab02b76311087873257071559edcaf6d7ab99" + "reference": "9a1efc8c10b86bcedc9233affd10c716b54ca1b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/f46ab02b76311087873257071559edcaf6d7ab99", - "reference": "f46ab02b76311087873257071559edcaf6d7ab99", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/9a1efc8c10b86bcedc9233affd10c716b54ca1b7", + "reference": "9a1efc8c10b86bcedc9233affd10c716b54ca1b7", "shasum": "" }, "require": { @@ -9310,7 +9495,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.4.8" + "source": "https://github.com/symfony/security-csrf/tree/v6.4.24" }, "funding": [ { @@ -9321,25 +9506,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/security-http", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "f6df97af71943cda726dc852335204eac02a716b" + "reference": "6c2e236f0fc3e0853770a5574ef7af471486ba4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/f6df97af71943cda726dc852335204eac02a716b", - "reference": "f6df97af71943cda726dc852335204eac02a716b", + "url": "https://api.github.com/repos/symfony/security-http/zipball/6c2e236f0fc3e0853770a5574ef7af471486ba4c", + "reference": "6c2e236f0fc3e0853770a5574ef7af471486ba4c", "shasum": "" }, "require": { @@ -9398,7 +9587,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.12" + "source": "https://github.com/symfony/security-http/tree/v6.4.26" }, "funding": [ { @@ -9409,25 +9598,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:18:25+00:00" + "time": "2025-09-05T18:17:25+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.12", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "10ae9c1b90f4809ccb7277cc8fe8d80b3af4412c" + "reference": "28779bbdb398cac3421d0e51f7ca669e4a27c5ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/10ae9c1b90f4809ccb7277cc8fe8d80b3af4412c", - "reference": "10ae9c1b90f4809ccb7277cc8fe8d80b3af4412c", + "url": "https://api.github.com/repos/symfony/serializer/zipball/28779bbdb398cac3421d0e51f7ca669e4a27c5ac", + "reference": "28779bbdb398cac3421d0e51f7ca669e4a27c5ac", "shasum": "" }, "require": { @@ -9496,7 +9689,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.12" + "source": "https://github.com/symfony/serializer/tree/v6.4.27" }, "funding": [ { @@ -9507,25 +9700,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2025-10-08T04:24:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -9538,12 +9735,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -9579,7 +9776,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -9590,25 +9787,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "63e069eb616049632cde9674c46957819454b8aa" + "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/63e069eb616049632cde9674c46957819454b8aa", - "reference": "63e069eb616049632cde9674c46957819454b8aa", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b67e94e06a05d9572c2fa354483b3e13e3cb1898", + "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898", "shasum": "" }, "require": { @@ -9641,7 +9842,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.8" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.24" }, "funding": [ { @@ -9652,25 +9853,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/string", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b" + "reference": "5621f039a71a11c87c106c1c598bdcd04a19aeea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/f8a1ccebd0997e16112dfecfd74220b78e5b284b", - "reference": "f8a1ccebd0997e16112dfecfd74220b78e5b284b", + "url": "https://api.github.com/repos/symfony/string/zipball/5621f039a71a11c87c106c1c598bdcd04a19aeea", + "reference": "5621f039a71a11c87c106c1c598bdcd04a19aeea", "shasum": "" }, "require": { @@ -9684,7 +9889,6 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", "symfony/http-client": "^5.4|^6.0|^7.0", "symfony/intl": "^6.2|^7.0", "symfony/translation-contracts": "^2.5|^3.0", @@ -9727,7 +9931,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.12" + "source": "https://github.com/symfony/string/tree/v6.4.26" }, "funding": [ { @@ -9738,25 +9942,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2025-09-11T14:32:46+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "65a8bc82080447fae78373aa10f8d13b38338977" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", + "reference": "65a8bc82080447fae78373aa10f8d13b38338977", "shasum": "" }, "require": { @@ -9764,12 +9972,12 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.6-dev" } }, "autoload": { @@ -9805,7 +10013,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" }, "funding": [ { @@ -9816,25 +10024,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.12", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "09c0df13f822a1b80c5972ca1aa9eeb1288e1194" + "reference": "9d13e87591c9de3221c8d6f23cd9a2b5958607bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/09c0df13f822a1b80c5972ca1aa9eeb1288e1194", - "reference": "09c0df13f822a1b80c5972ca1aa9eeb1288e1194", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9d13e87591c9de3221c8d6f23cd9a2b5958607bf", + "reference": "9d13e87591c9de3221c8d6f23cd9a2b5958607bf", "shasum": "" }, "require": { @@ -9865,7 +10077,7 @@ "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4|^7.0", + "symfony/form": "^6.4.20|^7.2.5", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -9914,7 +10126,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.12" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.25" }, "funding": [ { @@ -9925,25 +10137,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-15T06:35:36+00:00" + "time": "2025-08-13T09:41:44+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.4.12", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "4e63369647e3924e110b37337c6a58aac3086ad4" + "reference": "3b48b6e8225495c6d2438828982b4d219ca565ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/4e63369647e3924e110b37337c6a58aac3086ad4", - "reference": "4e63369647e3924e110b37337c6a58aac3086ad4", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/3b48b6e8225495c6d2438828982b4d219ca565ba", + "reference": "3b48b6e8225495c6d2438828982b4d219ca565ba", "shasum": "" }, "require": { @@ -9998,7 +10214,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.12" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.24" }, "funding": [ { @@ -10009,25 +10225,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-08T12:30:05+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/uid", - "version": "v6.4.12", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "2f16054e0a9b194b8ca581d4a64eee3f7d4a9d4d" + "reference": "17da16a750541a42cf2183935e0f6008316c23f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/2f16054e0a9b194b8ca581d4a64eee3f7d4a9d4d", - "reference": "2f16054e0a9b194b8ca581d4a64eee3f7d4a9d4d", + "url": "https://api.github.com/repos/symfony/uid/zipball/17da16a750541a42cf2183935e0f6008316c23f7", + "reference": "17da16a750541a42cf2183935e0f6008316c23f7", "shasum": "" }, "require": { @@ -10072,7 +10292,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.12" + "source": "https://github.com/symfony/uid/tree/v6.4.24" }, "funding": [ { @@ -10083,25 +10303,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:32:26+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/validator", - "version": "v6.4.12", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "6da1f0a1ee73d060a411d832cbe0539cfe9bbaa0" + "reference": "99df8a769e64e399f510166141ea74f450e8dd1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/6da1f0a1ee73d060a411d832cbe0539cfe9bbaa0", - "reference": "6da1f0a1ee73d060a411d832cbe0539cfe9bbaa0", + "url": "https://api.github.com/repos/symfony/validator/zipball/99df8a769e64e399f510166141ea74f450e8dd1d", + "reference": "99df8a769e64e399f510166141ea74f450e8dd1d", "shasum": "" }, "require": { @@ -10169,7 +10393,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.12" + "source": "https://github.com/symfony/validator/tree/v6.4.29" }, "funding": [ { @@ -10180,25 +10404,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-20T08:18:25+00:00" + "time": "2025-11-06T20:26:06+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.11", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "ee14c8254a480913268b1e3b1cba8045ed122694" + "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/ee14c8254a480913268b1e3b1cba8045ed122694", - "reference": "ee14c8254a480913268b1e3b1cba8045ed122694", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cfae1497a2f1eaad78dbc0590311c599c7178d4a", + "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a", "shasum": "" }, "require": { @@ -10210,7 +10438,6 @@ "symfony/console": "<5.4" }, "require-dev": { - "ext-iconv": "*", "symfony/console": "^5.4|^6.0|^7.0", "symfony/error-handler": "^6.3|^7.0", "symfony/http-kernel": "^5.4|^6.0|^7.0", @@ -10254,7 +10481,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.11" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.26" }, "funding": [ { @@ -10265,25 +10492,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-30T16:03:21+00:00" + "time": "2025-09-25T15:37:27+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.9", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e" + "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f9a060622e0d93777b7f8687ec4860191e16802e", - "reference": "f9a060622e0d93777b7f8687ec4860191e16802e", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc", + "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc", "shasum": "" }, "require": { @@ -10331,7 +10562,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.9" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.26" }, "funding": [ { @@ -10342,25 +10573,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-06-24T15:53:56+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/web-link", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "304c67cefe7128ea3957e9bb1ac6ce08a90a635b" + "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/304c67cefe7128ea3957e9bb1ac6ce08a90a635b", - "reference": "304c67cefe7128ea3957e9bb1ac6ce08a90a635b", + "url": "https://api.github.com/repos/symfony/web-link/zipball/75ffbb304f26a716969863328c8c6a11eadcfa5a", + "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a", "shasum": "" }, "require": { @@ -10414,7 +10649,7 @@ "push" ], "support": { - "source": "https://github.com/symfony/web-link/tree/v6.4.8" + "source": "https://github.com/symfony/web-link/tree/v6.4.24" }, "funding": [ { @@ -10425,25 +10660,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.12", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "762ee56b2649659380e0ef4d592d807bc17b7971" + "reference": "0fc8b966fd0dcaab544ae59bfc3a433f048c17b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/762ee56b2649659380e0ef4d592d807bc17b7971", - "reference": "762ee56b2649659380e0ef4d592d807bc17b7971", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0fc8b966fd0dcaab544ae59bfc3a433f048c17b0", + "reference": "0fc8b966fd0dcaab544ae59bfc3a433f048c17b0", "shasum": "" }, "require": { @@ -10486,7 +10725,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.12" + "source": "https://github.com/symfony/yaml/tree/v6.4.26" }, "funding": [ { @@ -10497,35 +10736,39 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-17T12:47:12+00:00" + "time": "2025-09-26T15:07:38+00:00" }, { "name": "twig/twig", - "version": "v3.14.0", + "version": "v3.22.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72" + "reference": "4509984193026de413baf4ba80f68590a7f2c51d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72", - "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/4509984193026de413baf4ba80f68590a7f2c51d", + "reference": "4509984193026de413baf4ba80f68590a7f2c51d", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1.0", "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "^1.8", - "symfony/polyfill-mbstring": "^1.3", - "symfony/polyfill-php81": "^1.29" + "symfony/polyfill-mbstring": "^1.3" }, "require-dev": { + "phpstan/phpstan": "^2.0", "psr/container": "^1.0|^2.0", "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0" }, @@ -10569,7 +10812,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.14.0" + "source": "https://github.com/twigphp/Twig/tree/v3.22.0" }, "funding": [ { @@ -10581,24 +10824,24 @@ "type": "tidelift" } ], - "time": "2024-09-09T17:55:12+00:00" + "time": "2025-10-29T15:56:47+00:00" }, { "name": "vich/uploader-bundle", - "version": "v2.4.2", + "version": "v2.8.1", "source": { "type": "git", "url": "https://github.com/dustin10/VichUploaderBundle.git", - "reference": "5eb6c3a19655383e392816bc5d1c9f069fbe2414" + "reference": "0619f0831003a16c65c6e038833430318705cbe1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/5eb6c3a19655383e392816bc5d1c9f069fbe2414", - "reference": "5eb6c3a19655383e392816bc5d1c9f069fbe2414", + "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/0619f0831003a16c65c6e038833430318705cbe1", + "reference": "0619f0831003a16c65c6e038833430318705cbe1", "shasum": "" }, "require": { - "doctrine/persistence": "^3.0", + "doctrine/persistence": "^3.0 || ^4.0", "ext-simplexml": "*", "jms/metadata": "^2.4", "php": "^8.1", @@ -10617,17 +10860,18 @@ "league/flysystem": "<2.0" }, "require-dev": { - "dg/bypass-finals": "^1.8", + "dg/bypass-finals": "^1.9", + "doctrine/common": "^3.0", "doctrine/doctrine-bundle": "^2.7", "doctrine/mongodb-odm": "^2.4", - "doctrine/orm": "^2.13", + "doctrine/orm": "^2.13 || ^3.0", "ext-sqlite3": "*", "knplabs/knp-gaufrette-bundle": "dev-master", "league/flysystem-bundle": "^2.4 || ^3.0", "league/flysystem-memory": "^2.0 || ^3.0", "matthiasnoback/symfony-dependency-injection-test": "^5.1", "mikey179/vfsstream": "^1.6.11", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^10.5 || ^11.5 || ^12.0", "symfony/asset": "^5.4 || ^6.0 || ^7.0", "symfony/browser-kit": "^5.4 || ^6.0 || ^7.0", "symfony/css-selector": "^5.4 || ^6.0 || ^7.0", @@ -10635,18 +10879,16 @@ "symfony/dom-crawler": "^5.4 || ^6.0 || ^7.0", "symfony/form": "^5.4 || ^6.0 || ^7.0", "symfony/framework-bundle": "^5.4 || ^6.0 || ^7.0", - "symfony/phpunit-bridge": "^7.0", + "symfony/phpunit-bridge": "^7.2", "symfony/security-csrf": "^5.4 || ^6.0 || ^7.0", "symfony/translation": "^5.4 || ^6.0 || ^7.0", "symfony/twig-bridge": "^5.4 || ^6.0 || ^7.0", "symfony/twig-bundle": "^5.4 || ^6.0 || ^7.0", "symfony/validator": "^5.4 || ^6.0 || ^7.0", "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0", - "yoast/phpunit-polyfills": "^2.0" + "symfony/yaml": "^5.4 || ^6.0 || ^7.0" }, "suggest": { - "doctrine/annotations": "If you use doctrine/doctrine-bundle >2.7, this package is required to use annotations", "doctrine/doctrine-bundle": "For integration with Doctrine", "doctrine/mongodb-odm-bundle": "For integration with Doctrine ODM", "doctrine/orm": "For integration with Doctrine ORM", @@ -10688,34 +10930,34 @@ ], "support": { "issues": "https://github.com/dustin10/VichUploaderBundle/issues", - "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.4.2" + "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.8.1" }, - "time": "2024-10-12T17:01:14+00:00" + "time": "2025-09-12T07:17:19+00:00" }, { "name": "webmozart/assert", - "version": "1.11.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/webmozarts/assert.git", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", - "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", "shasum": "" }, "require": { "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", "php": "^7.2 || ^8.0" }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<4.6.1 || 4.6.2" - }, - "require-dev": { - "phpunit/phpunit": "^8.5.13" + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" }, "type": "library", "extra": { @@ -10746,9 +10988,9 @@ ], "support": { "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.11.0" + "source": "https://github.com/webmozarts/assert/tree/1.12.1" }, - "time": "2022-06-03T18:03:27+00:00" + "time": "2025-10-29T15:56:20+00:00" }, { "name": "willdurand/negotiation", @@ -10810,16 +11052,16 @@ "packages-dev": [ { "name": "amphp/amp", - "version": "v2.6.4", + "version": "v2.6.5", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" + "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", - "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "url": "https://api.github.com/repos/amphp/amp/zipball/d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", + "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", "shasum": "" }, "require": { @@ -10835,11 +11077,6 @@ "vimeo/psalm": "^3.12" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, "autoload": { "files": [ "lib/functions.php", @@ -10887,7 +11124,7 @@ "support": { "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.4" + "source": "https://github.com/amphp/amp/tree/v2.6.5" }, "funding": [ { @@ -10895,7 +11132,7 @@ "type": "github" } ], - "time": "2024-03-21T18:52:26+00:00" + "time": "2025-09-03T19:41:28+00:00" }, { "name": "amphp/byte-stream", @@ -11007,22 +11244,23 @@ }, { "name": "doctrine/data-fixtures", - "version": "1.7.0", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "bbcb74f2ac6dbe81a14b3c3687d7623490a0448f" + "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/bbcb74f2ac6dbe81a14b3c3687d7623490a0448f", - "reference": "bbcb74f2ac6dbe81a14b3c3687d7623490a0448f", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/6fb221da56dae2011b33d47508e3b8aeb1d91db5", + "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5", "shasum": "" }, "require": { "doctrine/deprecations": "^0.5.3 || ^1.0", - "doctrine/persistence": "^2.0|^3.0", - "php": "^7.4 || ^8.0" + "doctrine/persistence": "^2.0 || ^3.0", + "php": "^7.4 || ^8.0", + "symfony/polyfill-php80": "^1" }, "conflict": { "doctrine/dbal": "<3.5 || >=5", @@ -11031,16 +11269,17 @@ }, "require-dev": { "doctrine/annotations": "^1.12 || ^2", - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^13", "doctrine/dbal": "^3.5 || ^4", "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", "doctrine/orm": "^2.14 || ^3", "ext-sqlite3": "*", - "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.6.13 || ^10.4.2", + "fig/log-test": "^1", + "phpstan/phpstan": "2.1.17", + "phpunit/phpunit": "^9.6.13 || 10.5.45", + "psr/log": "^1.1 || ^2 || ^3", "symfony/cache": "^5.4 || ^6.3 || ^7", - "symfony/var-exporter": "^5.4 || ^6.3 || ^7", - "vimeo/psalm": "^5.9" + "symfony/var-exporter": "^5.4 || ^6.3 || ^7" }, "suggest": { "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", @@ -11071,7 +11310,7 @@ ], "support": { "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.7.0" + "source": "https://github.com/doctrine/data-fixtures/tree/1.8.2" }, "funding": [ { @@ -11087,53 +11326,60 @@ "type": "tidelift" } ], - "time": "2023-11-24T11:18:31+00:00" + "time": "2025-06-10T07:00:05+00:00" }, { "name": "ergebnis/composer-normalize", - "version": "2.44.0", + "version": "2.48.2", "source": { "type": "git", "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "bd0c446426bb837ae0cc9f97948167e658bd11d2" + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/bd0c446426bb837ae0cc9f97948167e658bd11d2", - "reference": "bd0c446426bb837ae0cc9f97948167e658bd11d2", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", "shasum": "" }, "require": { "composer-plugin-api": "^2.0.0", - "ergebnis/json": "^1.2.0", - "ergebnis/json-normalizer": "^4.5.0", - "ergebnis/json-printer": "^3.5.0", + "ergebnis/json": "^1.4.0", + "ergebnis/json-normalizer": "^4.9.0", + "ergebnis/json-printer": "^3.7.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "localheinz/diff": "^1.1.1", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "localheinz/diff": "^1.3.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "composer/composer": "^2.7.7", - "ergebnis/license": "^2.5.0", - "ergebnis/php-cs-fixer-config": "^6.37.0", - "ergebnis/phpunit-slow-test-detector": "^2.16.0", - "fakerphp/faker": "^1.23.1", + "composer/composer": "^2.8.3", + "ergebnis/license": "^2.7.0", + "ergebnis/php-cs-fixer-config": "^6.53.0", + "ergebnis/phpstan-rules": "^2.11.0", + "ergebnis/phpunit-slow-test-detector": "^2.20.0", + "fakerphp/faker": "^1.24.1", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", "phpunit/phpunit": "^9.6.20", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "symfony/filesystem": "^5.4.41", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^2.1.4", + "symfony/filesystem": "^5.4.41" }, "type": "composer-plugin", "extra": { "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", + "branch-alias": { + "dev-main": "2.49-dev" + }, + "plugin-optional": true, "composer-normalize": { "indent-size": 2, "indent-style": "space" - }, - "plugin-optional": true + } }, "autoload": { "psr-4": { @@ -11164,40 +11410,48 @@ "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2024-09-30T21:56:22+00:00" + "time": "2025-09-06T11:42:34+00:00" }, { "name": "ergebnis/json", - "version": "1.3.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json.git", - "reference": "84051b4e243d6a8e2f8271604b11ffa52d29bc7a" + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json/zipball/84051b4e243d6a8e2f8271604b11ffa52d29bc7a", - "reference": "84051b4e243d6a8e2f8271604b11ffa52d29bc7a", + "url": "https://api.github.com/repos/ergebnis/json/zipball/7b56d2b5d9e897e75b43e2e753075a0904c921b1", + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1", "shasum": "" }, "require": { "ext-json": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpstan-rules": "^2.11.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.18", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.22", + "phpstan/phpstan-deprecation-rules": "^2.0.3", + "phpstan/phpstan-phpunit": "^2.0.7", + "phpstan/phpstan-strict-rules": "^2.0.6", + "phpunit/phpunit": "^9.6.24", + "rector/rector": "^2.1.4" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "1.7-dev" + }, "composer-normalize": { "indent-size": 2, "indent-style": "space" @@ -11229,20 +11483,20 @@ "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json" }, - "time": "2024-09-27T15:01:05+00:00" + "time": "2025-09-06T09:08:45+00:00" }, { "name": "ergebnis/json-normalizer", - "version": "4.6.0", + "version": "4.10.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-normalizer.git", - "reference": "859fd3cee417f0b10a8e6ffb8dbeb03587106b8b" + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/859fd3cee417f0b10a8e6ffb8dbeb03587106b8b", - "reference": "859fd3cee417f0b10a8e6ffb8dbeb03587106b8b", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/77961faf2c651c3f05977b53c6c68e8434febf62", + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62", "shasum": "" }, "require": { @@ -11251,26 +11505,39 @@ "ergebnis/json-printer": "^3.5.0", "ergebnis/json-schema-validator": "^4.2.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "composer/semver": "^3.4.3", - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^1.2.10" }, "suggest": { "composer/semver": "If you want to use ComposerJsonNormalizer or VersionConstraintNormalizer" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.11-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { "psr-4": { "Ergebnis\\Json\\Normalizer\\": "src/" @@ -11298,24 +11565,24 @@ "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-normalizer" }, - "time": "2024-09-27T15:11:59+00:00" + "time": "2025-09-06T09:18:13+00:00" }, { "name": "ergebnis/json-pointer", - "version": "3.5.0", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-pointer.git", - "reference": "f6ff71e69305b8ab5e4457e374b35dcd0812609b" + "reference": "43bef355184e9542635e35dd2705910a3df4c236" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/f6ff71e69305b8ab5e4457e374b35dcd0812609b", - "reference": "f6ff71e69305b8ab5e4457e374b35dcd0812609b", + "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/43bef355184e9542635e35dd2705910a3df4c236", + "reference": "43bef355184e9542635e35dd2705910a3df4c236", "shasum": "" }, "require": { - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.43.0", @@ -11325,15 +11592,18 @@ "ergebnis/phpunit-slow-test-detector": "^2.15.0", "fakerphp/faker": "^1.23.1", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.1", - "vimeo/psalm": "^5.25.0" + "rector/rector": "^1.2.10" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.4-dev" + "dev-main": "3.8-dev" }, "composer-normalize": { "indent-size": 2, @@ -11368,40 +11638,53 @@ "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-pointer" }, - "time": "2024-09-27T15:47:15+00:00" + "time": "2025-09-06T09:28:19+00:00" }, { "name": "ergebnis/json-printer", - "version": "3.6.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-printer.git", - "reference": "d2e51379dc62d73017a779a78fcfba568de39e0a" + "reference": "211d73fc7ec6daf98568ee6ed6e6d133dee8503e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/d2e51379dc62d73017a779a78fcfba568de39e0a", - "reference": "d2e51379dc62d73017a779a78fcfba568de39e0a", + "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/211d73fc7ec6daf98568ee6ed6e6d133dee8503e", + "reference": "211d73fc7ec6daf98568ee6ed6e6d133dee8503e", "shasum": "" }, "require": { "ext-json": "*", "ext-mbstring": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", - "phpunit/phpunit": "^9.6.19", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "~1.2.5", - "vimeo/psalm": "^5.26.1" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.1", + "phpstan/phpstan-strict-rules": "^1.6.1", + "phpunit/phpunit": "^9.6.21", + "rector/rector": "^1.2.10" }, "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.9-dev" + }, + "composer-normalize": { + "indent-size": 2, + "indent-style": "space" + } + }, "autoload": { "psr-4": { "Ergebnis\\Json\\Printer\\": "src/" @@ -11430,43 +11713,50 @@ "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-printer" }, - "time": "2024-09-27T15:19:56+00:00" + "time": "2025-09-06T09:59:26+00:00" }, { "name": "ergebnis/json-schema-validator", - "version": "4.3.0", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-schema-validator.git", - "reference": "73f938f8995c6ad1e37d2c1dfeaa8336861f9db8" + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/73f938f8995c6ad1e37d2c1dfeaa8336861f9db8", - "reference": "73f938f8995c6ad1e37d2c1dfeaa8336861f9db8", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/b739527a480a9e3651360ad351ea77e7e9019df2", + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2", "shasum": "" }, "require": { "ergebnis/json": "^1.2.0", "ergebnis/json-pointer": "^3.4.0", "ext-json": "*", - "justinrainbow/json-schema": "^5.2.12", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", + "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "ergebnis/data-provider": "^3.2.0", - "ergebnis/license": "^2.4.0", - "ergebnis/php-cs-fixer-config": "^6.36.0", - "ergebnis/phpunit-slow-test-detector": "^2.15.1", - "fakerphp/faker": "^1.23.1", + "ergebnis/composer-normalize": "^2.44.0", + "ergebnis/data-provider": "^3.3.0", + "ergebnis/license": "^2.5.0", + "ergebnis/php-cs-fixer-config": "^6.37.0", + "ergebnis/phpunit-slow-test-detector": "^2.16.1", + "fakerphp/faker": "^1.24.0", "infection/infection": "~0.26.6", + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.10", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", "phpunit/phpunit": "^9.6.20", - "psalm/plugin-phpunit": "~0.19.0", - "rector/rector": "^1.2.5", - "vimeo/psalm": "^5.26.1" + "rector/rector": "^1.2.10" }, "type": "library", "extra": { + "branch-alias": { + "dev-main": "4.6-dev" + }, "composer-normalize": { "indent-size": 2, "indent-style": "space" @@ -11500,20 +11790,20 @@ "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-schema-validator" }, - "time": "2024-09-27T15:16:33+00:00" + "time": "2025-09-06T11:37:35+00:00" }, { "name": "fakerphp/faker", - "version": "v1.23.1", + "version": "v1.24.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { @@ -11561,9 +11851,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" }, - "time": "2024-01-02T13:46:09+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { "name": "felixfbecker/advanced-json-rpc", @@ -11700,10 +11990,10 @@ }, "type": "symfony-bundle", "extra": { + "bin-dir": "bin", "branch-alias": { "dev-master": "2.x-dev" }, - "bin-dir": "bin", "sort-packages": true }, "autoload": { @@ -11742,23 +12032,23 @@ }, { "name": "localheinz/diff", - "version": "1.1.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/localheinz/diff.git", - "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c" + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/localheinz/diff/zipball/851bb20ea8358c86f677f5f111c4ab031b1c764c", - "reference": "851bb20ea8358c86f677f5f111c4ab031b1c764c", + "url": "https://api.github.com/repos/localheinz/diff/zipball/33bd840935970cda6691c23fc7d94ae764c0734c", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8.0", + "phpunit/phpunit": "^7.5.0 || ^8.5.23", "symfony/process": "^4.2 || ^5" }, "type": "library", @@ -11790,28 +12080,23 @@ "unified diff" ], "support": { - "source": "https://github.com/localheinz/diff/tree/main" + "issues": "https://github.com/localheinz/diff/issues", + "source": "https://github.com/localheinz/diff/tree/1.3.0" }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2020-07-06T04:49:32+00:00" + "time": "2025-08-30T09:44:18+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -11850,7 +12135,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -11858,27 +12143,28 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nelmio/alice", - "version": "3.13.6", + "version": "3.14.2", "source": { "type": "git", "url": "https://github.com/nelmio/alice.git", - "reference": "76caab8675c68956d56a2dd03f66384251e0aa7c" + "reference": "f353866956ac4760514e24e8d51902d261d50489" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/alice/zipball/76caab8675c68956d56a2dd03f66384251e0aa7c", - "reference": "76caab8675c68956d56a2dd03f66384251e0aa7c", + "url": "https://api.github.com/repos/nelmio/alice/zipball/f353866956ac4760514e24e8d51902d261d50489", + "reference": "f353866956ac4760514e24e8d51902d261d50489", "shasum": "" }, "require": { "fakerphp/faker": "^1.10", "myclabs/deep-copy": "^1.10", "php": "^8.1", - "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0", + "sebastian/comparator": "^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0", + "symfony/polyfill-php84": "^1.31", "symfony/property-access": "^6.4 || ^7.0", "symfony/yaml": "^6.0 || ^7.0" }, @@ -11945,7 +12231,7 @@ ], "support": { "issues": "https://github.com/nelmio/alice/issues", - "source": "https://github.com/nelmio/alice/tree/3.13.6" + "source": "https://github.com/nelmio/alice/tree/3.14.2" }, "funding": [ { @@ -11953,7 +12239,7 @@ "type": "github" } ], - "time": "2024-07-03T17:54:12+00:00" + "time": "2025-02-26T09:01:07+00:00" }, { "name": "netresearch/jsonmapper", @@ -12182,16 +12468,11 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.7", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0" - }, + "version": "1.12.32", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", - "reference": "dc2b9976bd8b0f84ec9b0e50cc35378551de7af0", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", + "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", "shasum": "" }, "require": { @@ -12236,7 +12517,7 @@ "type": "github" } ], - "time": "2024-10-18T11:12:07+00:00" + "time": "2025-09-30T10:16:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -12559,16 +12840,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.21", + "version": "9.6.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa" + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", - "reference": "de6abf3b6f8dd955fac3caad3af7a9504e8c2ffa", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", "shasum": "" }, "require": { @@ -12579,7 +12860,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -12590,11 +12871,11 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.8", + "sebastian/comparator": "^4.0.9", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.6", - "sebastian/global-state": "^5.0.7", + "sebastian/exporter": "^4.0.8", + "sebastian/global-state": "^5.0.8", "sebastian/object-enumerator": "^4.0.4", "sebastian/resource-operations": "^3.0.4", "sebastian/type": "^3.2.1", @@ -12642,7 +12923,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.21" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.29" }, "funding": [ { @@ -12653,32 +12934,40 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2024-09-19T10:50:18+00:00" + "time": "2025-09-24T06:29:11+00:00" }, { "name": "psalm/plugin-symfony", - "version": "v5.2.5", + "version": "v5.2.6", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-symfony.git", - "reference": "fb801a9b3d12ace9fb619febfaa3ae0bc1dbb196" + "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/fb801a9b3d12ace9fb619febfaa3ae0bc1dbb196", - "reference": "fb801a9b3d12ace9fb619febfaa3ae0bc1dbb196", + "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/1638f172b4ae5f283ee6b1b58fff3e44aa628742", + "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742", "shasum": "" }, "require": { "ext-simplexml": "*", "php": "^8.1", "symfony/framework-bundle": "^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "^5.16" + "vimeo/psalm": "^5.16 || dev-master" }, "require-dev": { "doctrine/annotations": "^1.8|^2", @@ -12721,22 +13010,22 @@ "description": "Psalm Plugin for Symfony", "support": { "issues": "https://github.com/psalm/psalm-plugin-symfony/issues", - "source": "https://github.com/psalm/psalm-plugin-symfony/tree/v5.2.5" + "source": "https://github.com/psalm/psalm-plugin-symfony/tree/v5.2.6" }, - "time": "2024-07-03T11:57:02+00:00" + "time": "2024-12-21T08:46:26+00:00" }, { "name": "rector/rector", - "version": "1.2.8", + "version": "1.2.10", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "05755bf43617449c08ee8e50fb840c85ad3b1240" + "reference": "40f9cf38c05296bd32f444121336a521a293fa61" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/05755bf43617449c08ee8e50fb840c85ad3b1240", - "reference": "05755bf43617449c08ee8e50fb840c85ad3b1240", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/40f9cf38c05296bd32f444121336a521a293fa61", + "reference": "40f9cf38c05296bd32f444121336a521a293fa61", "shasum": "" }, "require": { @@ -12774,7 +13063,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/1.2.8" + "source": "https://github.com/rectorphp/rector/tree/1.2.10" }, "funding": [ { @@ -12782,7 +13071,7 @@ "type": "github" } ], - "time": "2024-10-18T11:54:27+00:00" + "time": "2024-11-08T13:59:10+00:00" }, { "name": "sebastian/cli-parser", @@ -12953,16 +13242,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.8", + "version": "4.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", - "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", "shasum": "" }, "require": { @@ -13015,15 +13304,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/comparator", + "type": "tidelift" } ], - "time": "2022-09-14T12:41:17+00:00" + "time": "2025-08-10T06:51:50+00:00" }, { "name": "sebastian/complexity", @@ -13147,16 +13448,16 @@ }, { "name": "sebastian/exporter", - "version": "4.0.6", + "version": "4.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", - "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", "shasum": "" }, "require": { @@ -13212,28 +13513,40 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/exporter", + "type": "tidelift" } ], - "time": "2024-03-02T06:33:00+00:00" + "time": "2025-09-24T06:03:27+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.7", + "version": "5.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", - "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", "shasum": "" }, "require": { @@ -13276,15 +13589,27 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/global-state", + "type": "tidelift" } ], - "time": "2024-03-02T06:35:11+00:00" + "time": "2025-08-10T07:10:35+00:00" }, { "name": "sebastian/lines-of-code", @@ -13457,16 +13782,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.5", + "version": "4.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", - "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", + "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", "shasum": "" }, "require": { @@ -13508,15 +13833,27 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/sebastian/recursion-context", + "type": "tidelift" } ], - "time": "2023-02-03T06:07:39+00:00" + "time": "2025-08-10T06:57:39+00:00" }, { "name": "sebastian/resource-operations", @@ -13683,16 +14020,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.3.0", + "version": "3.4.1", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876" + "reference": "6a740f39415aee8886aea10333403adc77d50791" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/f56b220fe2db1ade4c88098d83413ebdfc3bf876", - "reference": "f56b220fe2db1ade4c88098d83413ebdfc3bf876", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/6a740f39415aee8886aea10333403adc77d50791", + "reference": "6a740f39415aee8886aea10333403adc77d50791", "shasum": "" }, "require": { @@ -13735,7 +14072,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.3.0" + "source": "https://github.com/spatie/array-to-xml/tree/3.4.1" }, "funding": [ { @@ -13747,20 +14084,20 @@ "type": "github" } ], - "time": "2024-05-01T10:20:27+00:00" + "time": "2025-11-12T10:32:50+00:00" }, { "name": "symfony/browser-kit", - "version": "v6.4.8", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "62ab90b92066ef6cce5e79365625b4b1432464c8" + "reference": "067e301786bbb58048077fc10507aceb18226e23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/62ab90b92066ef6cce5e79365625b4b1432464c8", - "reference": "62ab90b92066ef6cce5e79365625b4b1432464c8", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/067e301786bbb58048077fc10507aceb18226e23", + "reference": "067e301786bbb58048077fc10507aceb18226e23", "shasum": "" }, "require": { @@ -13799,7 +14136,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v6.4.8" + "source": "https://github.com/symfony/browser-kit/tree/v6.4.28" }, "funding": [ { @@ -13810,25 +14147,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-10-16T22:35:35+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.8", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "4b61b02fe15db48e3687ce1c45ea385d1780fe08" + "reference": "9b784413143701aa3c94ac1869a159a9e53e8761" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/4b61b02fe15db48e3687ce1c45ea385d1780fe08", - "reference": "4b61b02fe15db48e3687ce1c45ea385d1780fe08", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/9b784413143701aa3c94ac1869a159a9e53e8761", + "reference": "9b784413143701aa3c94ac1869a159a9e53e8761", "shasum": "" }, "require": { @@ -13864,7 +14205,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.8" + "source": "https://github.com/symfony/css-selector/tree/v6.4.24" }, "funding": [ { @@ -13875,25 +14216,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/debug-bundle", - "version": "v6.4.8", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "689f1bcb0bd3b945e3c671cbd06274b127c64dc9" + "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/689f1bcb0bd3b945e3c671cbd06274b127c64dc9", - "reference": "689f1bcb0bd3b945e3c671cbd06274b127c64dc9", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/21a61c55192d558a6b81cdb12e8c010fc9474fe0", + "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0", "shasum": "" }, "require": { @@ -13938,7 +14283,7 @@ "description": "Provides a tight integration of the Symfony VarDumper component and the ServerLogCommand from MonologBridge into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug-bundle/tree/v6.4.8" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.27" }, "funding": [ { @@ -13949,25 +14294,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2025-10-11T17:35:31+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.61.0", + "version": "v1.62.1", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "a3b7f14d349f8f44ed752d4dde2263f77510cc18" + "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/a3b7f14d349f8f44ed752d4dde2263f77510cc18", - "reference": "a3b7f14d349f8f44ed752d4dde2263f77510cc18", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/468ff2708200c95ebc0d85d3174b6c6711b8a590", + "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590", "shasum": "" }, "require": { @@ -14030,7 +14379,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.61.0" + "source": "https://github.com/symfony/maker-bundle/tree/v1.62.1" }, "funding": [ { @@ -14046,20 +14395,20 @@ "type": "tidelift" } ], - "time": "2024-08-29T22:50:23+00:00" + "time": "2025-01-15T00:21:40+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.11", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "168f412dcd6caf3813a9cc0f286cd68f6a76f070" + "reference": "406aa80401bf960e7a173a3ccf268ae82b6bc93f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/168f412dcd6caf3813a9cc0f286cd68f6a76f070", - "reference": "168f412dcd6caf3813a9cc0f286cd68f6a76f070", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/406aa80401bf960e7a173a3ccf268ae82b6bc93f", + "reference": "406aa80401bf960e7a173a3ccf268ae82b6bc93f", "shasum": "" }, "require": { @@ -14079,8 +14428,8 @@ "type": "symfony-bridge", "extra": { "thanks": { - "name": "phpunit/phpunit", - "url": "https://github.com/sebastianbergmann/phpunit" + "url": "https://github.com/sebastianbergmann/phpunit", + "name": "phpunit/phpunit" } }, "autoload": { @@ -14111,8 +14460,11 @@ ], "description": "Provides utilities for PHPUnit, especially user deprecation notices management", "homepage": "https://symfony.com", + "keywords": [ + "testing" + ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.11" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.26" }, "funding": [ { @@ -14123,25 +14475,29 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-13T14:27:37+00:00" + "time": "2025-09-12T08:37:02+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.11", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "ef4b8b4f9f51260d18abec40ceacc4bc9c5555e3" + "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/ef4b8b4f9f51260d18abec40ceacc4bc9c5555e3", - "reference": "ef4b8b4f9f51260d18abec40ceacc4bc9c5555e3", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", + "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", "shasum": "" }, "require": { @@ -14194,7 +14550,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.11" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.27" }, "funding": [ { @@ -14205,49 +14561,58 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2025-10-05T13:55:43+00:00" }, { "name": "theofidry/alice-data-fixtures", - "version": "1.7.2", + "version": "1.8.3", "source": { "type": "git", "url": "https://github.com/theofidry/AliceDataFixtures.git", - "reference": "39a2fb2d83d683bec58e9fa0c1e22feceb17056e" + "reference": "711b52f6a3916b1e92c3270420baad1309443b8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/AliceDataFixtures/zipball/39a2fb2d83d683bec58e9fa0c1e22feceb17056e", - "reference": "39a2fb2d83d683bec58e9fa0c1e22feceb17056e", + "url": "https://api.github.com/repos/theofidry/AliceDataFixtures/zipball/711b52f6a3916b1e92c3270420baad1309443b8f", + "reference": "711b52f6a3916b1e92c3270420baad1309443b8f", "shasum": "" }, "require": { "nelmio/alice": "^3.10", - "php": "^8.2", + "php": "^8.3", "psr/log": "^1 || ^2 || ^3", "webmozart/assert": "^1.10" }, "conflict": { + "doctrine/data-fixtures": "<1.7.0", "doctrine/dbal": "<3.0", - "doctrine/orm": "<2.6.3", - "doctrine/persistence": "<2.0", - "illuminate/database": "<8.12", + "doctrine/doctrine-bundle": "<2.11.0", + "doctrine/mongodb-odm": "<2.6.0", + "doctrine/mongodb-odm-bundle": "<5.1.0", + "doctrine/orm": "<2.20 || >=3.0", + "doctrine/persistence": "<2.5.7 || >=3.0 <3.4.0", + "doctrine/phpcr-bundle": "<3.0", + "doctrine/phpcr-odm": "<2.0.0", + "illuminate/database": "<10.0", "ocramius/proxy-manager": "<2.1", - "symfony/framework-bundle": "<5.4 || >=6.0 <6.4", + "symfony/framework-bundle": ">=6.0 <6.4.19", "zendframework/zend-code": "<3.3.1" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4.1", - "doctrine/annotations": "^1.13", - "phpspec/prophecy": "^1.14.0", - "phpspec/prophecy-phpunit": "^2.0.1", - "phpunit/phpunit": "^9.5.10", - "symfony/phpunit-bridge": "^5.3.8 || ^6.4" + "phpspec/prophecy": "^1.20.0", + "phpspec/prophecy-phpunit": "^2.3.0", + "phpunit/phpunit": "^11.5.12", + "symfony/phpunit-bridge": "^7.2" }, "suggest": { "alcaeus/mongo-php-adapter": "To use Doctrine with the MongoDB flavour", @@ -14298,7 +14663,7 @@ ], "support": { "issues": "https://github.com/theofidry/AliceDataFixtures/issues", - "source": "https://github.com/theofidry/AliceDataFixtures/tree/1.7.2" + "source": "https://github.com/theofidry/AliceDataFixtures/tree/1.8.3" }, "funding": [ { @@ -14306,20 +14671,20 @@ "type": "github" } ], - "time": "2024-07-05T21:18:40+00:00" + "time": "2025-03-09T09:51:17+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.3", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", - "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c", + "reference": "b7489ce515e168639d17feec34b8847c326b0b3c", "shasum": "" }, "require": { @@ -14348,7 +14713,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + "source": "https://github.com/theseer/tokenizer/tree/1.3.1" }, "funding": [ { @@ -14356,7 +14721,7 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "vimeo/psalm", @@ -14433,11 +14798,11 @@ "type": "project", "extra": { "branch-alias": { - "dev-master": "5.x-dev", - "dev-4.x": "4.x-dev", - "dev-3.x": "3.x-dev", + "dev-1.x": "1.x-dev", "dev-2.x": "2.x-dev", - "dev-1.x": "1.x-dev" + "dev-3.x": "3.x-dev", + "dev-4.x": "4.x-dev", + "dev-master": "5.x-dev" } }, "autoload": { From 72c3e43de4c42cc4cea96a6fb454068df5c499a5 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 24 Nov 2025 07:00:31 +0100 Subject: [PATCH 27/47] 5740: Applied coding standards --- CHANGELOG.md | 2 + public/api-spec-v2.json | 78 ++++++++++++++++++++++++++ public/api-spec-v2.yaml | 52 +++++++++++++++++ src/Entity/ScreenLayout.php | 4 +- src/Entity/ScreenLayoutRegions.php | 2 +- src/Entity/Template.php | 2 +- src/Entity/Tenant.php | 2 +- src/Entity/Tenant/FeedSource.php | 2 +- src/Entity/Tenant/Media.php | 2 +- src/Entity/Tenant/Playlist.php | 10 ++-- src/Entity/Tenant/Screen.php | 6 +- src/Entity/Tenant/ScreenGroup.php | 4 +- src/Entity/Tenant/Slide.php | 4 +- src/Entity/Tenant/Theme.php | 2 +- src/Entity/Traits/MultiTenantTrait.php | 2 +- src/Entity/User.php | 2 +- src/Feed/BrndFeedType.php | 4 +- src/Feed/SourceType/Brnd/ApiClient.php | 6 +- 18 files changed, 159 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 552027526..e86c94405 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- [#330](https://github.com/os2display/display-api-service/pull/330) + - Composer update. - [#313](https://github.com/os2display/display-api-service/pull/313) - Add BRND booking feed type diff --git a/public/api-spec-v2.json b/public/api-spec-v2.json index a84f0bb98..9439d206c 100644 --- a/public/api-spec-v2.json +++ b/public/api-spec-v2.json @@ -439,6 +439,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Creates a Feed Source resource.", @@ -540,6 +543,9 @@ "422": { "description": "Unprocessable entity" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -596,6 +602,9 @@ "204": { "description": "FeedSource resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -3218,6 +3227,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Create Screen group resources.", @@ -3319,6 +3331,9 @@ "422": { "description": "Unprocessable entity" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -3375,6 +3390,9 @@ "204": { "description": "ScreenGroup resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -3568,6 +3586,9 @@ "204": { "description": "ScreenGroupCampaign resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -4097,6 +4118,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Creates a Screen resource.", @@ -4198,6 +4222,9 @@ "422": { "description": "Unprocessable entity" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -4254,6 +4281,9 @@ "204": { "description": "Screen resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -4488,6 +4518,9 @@ "204": { "description": "ScreenCampaign resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -4827,6 +4860,9 @@ "204": { "description": "PlaylistScreenRegion resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -5006,6 +5042,9 @@ } } } + }, + "403": { + "description": "Forbidden" } }, "summary": "Retrieve screen-groups from screen id.", @@ -5162,6 +5201,9 @@ "204": { "description": "ScreenGroup resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -6433,6 +6475,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Creates a Theme resource.", @@ -6534,6 +6579,9 @@ "422": { "description": "Unprocessable entity" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -6590,6 +6638,9 @@ "204": { "description": "Theme resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -6813,6 +6864,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Create a User resource.", @@ -6931,6 +6985,9 @@ "422": { "description": "Unprocessable entity" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -6987,6 +7044,9 @@ "204": { "description": "User resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -7168,6 +7228,9 @@ } } } + }, + "403": { + "description": "Forbidden" } }, "summary": "Retrieves the collection of UserActivationCode resources.", @@ -7240,6 +7303,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Create user activation code.", @@ -7302,6 +7368,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Use user activation code.", @@ -7364,6 +7433,9 @@ }, "422": { "description": "Unprocessable entity" + }, + "403": { + "description": "Forbidden" } }, "summary": "Refresh user activation code.", @@ -7420,6 +7492,9 @@ } } }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } @@ -7453,6 +7528,9 @@ "204": { "description": "UserActivationCode resource deleted" }, + "403": { + "description": "Forbidden" + }, "404": { "description": "Resource not found" } diff --git a/public/api-spec-v2.yaml b/public/api-spec-v2.yaml index 6a0489e3d..0391c09e9 100644 --- a/public/api-spec-v2.yaml +++ b/public/api-spec-v2.yaml @@ -334,6 +334,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Creates a Feed Source resource.' description: 'Creates a Feed Source resource.' parameters: [] @@ -403,6 +405,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Update a Feed Source resource.' @@ -443,6 +447,8 @@ paths: responses: '204': description: 'FeedSource resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a Feed Source resource.' @@ -2334,6 +2340,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Create Screen group resources.' description: 'Create Screen group resources.' parameters: [] @@ -2403,6 +2411,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Update a Screen group resource.' @@ -2443,6 +2453,8 @@ paths: responses: '204': description: 'ScreenGroup resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a Screen group resource.' @@ -2582,6 +2594,8 @@ paths: responses: '204': description: 'ScreenGroupCampaign resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a campaign from a screen group.' @@ -2945,6 +2959,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Creates a Screen resource.' description: 'Creates a Screen resource.' parameters: [] @@ -3014,6 +3030,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Update a Screen resource.' @@ -3054,6 +3072,8 @@ paths: responses: '204': description: 'Screen resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a Screen resource.' @@ -3222,6 +3242,8 @@ paths: responses: '204': description: 'ScreenCampaign resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a campaign from a screen.' @@ -3420,6 +3442,8 @@ paths: responses: '204': description: 'PlaylistScreenRegion resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Remove Playlist resource from screen region.' @@ -3497,6 +3521,8 @@ paths: type: array items: $ref: '#/components/schemas/ScreenGroup.ScreenGroup-screens.screen-groups.read' + '403': + description: Forbidden summary: 'Retrieve screen-groups from screen id.' description: 'Retrieve screen-groups from screen id.' parameters: @@ -3620,6 +3646,8 @@ paths: responses: '204': description: 'ScreenGroup resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a screen groups from a screen' @@ -4619,6 +4647,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Creates a Theme resource.' description: 'Creates a Theme resource.' parameters: [] @@ -4688,6 +4718,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Update a Theme resource.' @@ -4728,6 +4760,8 @@ paths: responses: '204': description: 'Theme resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete a Theme resource.' @@ -4906,6 +4940,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Create a User resource.' description: 'Create a User resource.' parameters: @@ -4989,6 +5025,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Update User resource.' @@ -5029,6 +5067,8 @@ paths: responses: '204': description: 'User resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Delete an User resource.' @@ -5104,6 +5144,8 @@ paths: type: array items: $ref: '#/components/schemas/UserActivationCode.UserActivationCode' + '403': + description: Forbidden summary: 'Retrieves the collection of UserActivationCode resources.' description: 'Retrieves the collection of UserActivationCode resources.' parameters: @@ -5158,6 +5200,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Create user activation code.' description: 'Create user activation code' parameters: [] @@ -5198,6 +5242,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Use user activation code.' description: 'Use user activation code.' parameters: [] @@ -5238,6 +5284,8 @@ paths: description: 'Invalid input' '422': description: 'Unprocessable entity' + '403': + description: Forbidden summary: 'Refresh user activation code.' description: 'Refresh user activation code.' parameters: [] @@ -5273,6 +5321,8 @@ paths: multipart/form-data: schema: $ref: '#/components/schemas/UserActivationCode' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Retrieves a UserActivationCode resource.' @@ -5298,6 +5348,8 @@ paths: responses: '204': description: 'UserActivationCode resource deleted' + '403': + description: Forbidden '404': description: 'Resource not found' summary: 'Removes the UserActivationCode resource.' diff --git a/src/Entity/ScreenLayout.php b/src/Entity/ScreenLayout.php index 73d034ba4..89b66e5af 100644 --- a/src/Entity/ScreenLayout.php +++ b/src/Entity/ScreenLayout.php @@ -31,13 +31,13 @@ class ScreenLayout extends AbstractBaseEntity implements MultiTenantInterface, R private int $gridColumns = 0; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: Screen::class, mappedBy: 'screenLayout')] private Collection $screens; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: ScreenLayoutRegions::class, mappedBy: 'screenLayout')] private Collection $regions; diff --git a/src/Entity/ScreenLayoutRegions.php b/src/Entity/ScreenLayoutRegions.php index 12b989552..0c5466511 100644 --- a/src/Entity/ScreenLayoutRegions.php +++ b/src/Entity/ScreenLayoutRegions.php @@ -39,7 +39,7 @@ class ScreenLayoutRegions extends AbstractBaseEntity implements MultiTenantInter private ?ScreenLayout $screenLayout = null; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: PlaylistScreenRegion::class, cascade: ['persist', 'remove'], mappedBy: 'region', orphanRemoval: true)] private Collection $playlistScreenRegions; diff --git a/src/Entity/Template.php b/src/Entity/Template.php index ce2579259..b85245388 100644 --- a/src/Entity/Template.php +++ b/src/Entity/Template.php @@ -32,7 +32,7 @@ class Template extends AbstractBaseEntity implements MultiTenantInterface, Relat private array $resources = []; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: Slide::class, mappedBy: 'template')] private Collection $slides; diff --git a/src/Entity/Tenant.php b/src/Entity/Tenant.php index 4a6ab4e6b..91008f673 100644 --- a/src/Entity/Tenant.php +++ b/src/Entity/Tenant.php @@ -20,7 +20,7 @@ class Tenant extends AbstractBaseEntity implements \JsonSerializable private string $tenantKey = ''; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: UserRoleTenant::class, mappedBy: 'tenant', orphanRemoval: true)] private Collection $userRoleTenants; diff --git a/src/Entity/Tenant/FeedSource.php b/src/Entity/Tenant/FeedSource.php index e52ac27cb..b580bfe7d 100644 --- a/src/Entity/Tenant/FeedSource.php +++ b/src/Entity/Tenant/FeedSource.php @@ -27,7 +27,7 @@ class FeedSource extends AbstractTenantScopedEntity implements RelationsChecksum private ?array $secrets = []; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: Feed::class, mappedBy: 'feedSource', orphanRemoval: true)] private Collection $feeds; diff --git a/src/Entity/Tenant/Media.php b/src/Entity/Tenant/Media.php index 91c0ea712..1b285648e 100644 --- a/src/Entity/Tenant/Media.php +++ b/src/Entity/Tenant/Media.php @@ -53,7 +53,7 @@ class Media extends AbstractTenantScopedEntity implements RelationsChecksumInter private string $sha = ''; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\ManyToMany(targetEntity: Slide::class, mappedBy: 'media')] private Collection $slides; diff --git a/src/Entity/Tenant/Playlist.php b/src/Entity/Tenant/Playlist.php index 9882e1dee..d565ff84a 100644 --- a/src/Entity/Tenant/Playlist.php +++ b/src/Entity/Tenant/Playlist.php @@ -29,32 +29,32 @@ class Playlist extends AbstractTenantScopedEntity implements MultiTenantInterfac private bool $isCampaign = false; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'campaign', targetEntity: ScreenCampaign::class, orphanRemoval: true)] private Collection $screenCampaigns; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'campaign', targetEntity: ScreenGroupCampaign::class, orphanRemoval: true)] private Collection $screenGroupCampaigns; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'playlist', targetEntity: PlaylistScreenRegion::class, orphanRemoval: true)] private Collection $playlistScreenRegions; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'playlist', targetEntity: PlaylistSlide::class, orphanRemoval: true)] #[ORM\OrderBy(['weight' => Order::Ascending->value])] private Collection $playlistSlides; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'playlist', targetEntity: Schedule::class, cascade: ['persist'], orphanRemoval: true)] private Collection $schedules; diff --git a/src/Entity/Tenant/Screen.php b/src/Entity/Tenant/Screen.php index ca4c54a4a..9fde5553e 100644 --- a/src/Entity/Tenant/Screen.php +++ b/src/Entity/Tenant/Screen.php @@ -44,20 +44,20 @@ class Screen extends AbstractTenantScopedEntity implements RelationsChecksumInte private ?ScreenUser $screenUser = null; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'screen', targetEntity: ScreenCampaign::class, orphanRemoval: true)] private Collection $screenCampaigns; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'screen', targetEntity: PlaylistScreenRegion::class, cascade: ['persist', 'remove'], orphanRemoval: true)] #[ORM\OrderBy(['weight' => \Doctrine\Common\Collections\Order::Ascending->value])] private Collection $playlistScreenRegions; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\ManyToMany(targetEntity: ScreenGroup::class, mappedBy: 'screens')] private Collection $screenGroups; diff --git a/src/Entity/Tenant/ScreenGroup.php b/src/Entity/Tenant/ScreenGroup.php index bd4046039..228ebe82d 100644 --- a/src/Entity/Tenant/ScreenGroup.php +++ b/src/Entity/Tenant/ScreenGroup.php @@ -20,13 +20,13 @@ class ScreenGroup extends AbstractTenantScopedEntity implements RelationsChecksu use RelationsChecksumTrait; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'screenGroup', targetEntity: ScreenGroupCampaign::class, orphanRemoval: true)] private Collection $screenGroupCampaigns; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\ManyToMany(targetEntity: Screen::class, inversedBy: 'screenGroups')] private Collection $screens; diff --git a/src/Entity/Tenant/Slide.php b/src/Entity/Tenant/Slide.php index e8639dcda..82e1fbd7f 100644 --- a/src/Entity/Tenant/Slide.php +++ b/src/Entity/Tenant/Slide.php @@ -40,13 +40,13 @@ class Slide extends AbstractTenantScopedEntity implements RelationsChecksumInter private ?Theme $theme = null; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\ManyToMany(targetEntity: Media::class, inversedBy: 'slides')] private Collection $media; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: PlaylistSlide::class, mappedBy: 'slide', fetch: 'EXTRA_LAZY', cascade: ['remove'])] private Collection $playlistSlides; diff --git a/src/Entity/Tenant/Theme.php b/src/Entity/Tenant/Theme.php index 5a25799a6..915e48c4d 100644 --- a/src/Entity/Tenant/Theme.php +++ b/src/Entity/Tenant/Theme.php @@ -27,7 +27,7 @@ class Theme extends AbstractTenantScopedEntity implements RelationsChecksumInter private ?Media $logo = null; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(mappedBy: 'theme', targetEntity: Slide::class)] private Collection $slides; diff --git a/src/Entity/Traits/MultiTenantTrait.php b/src/Entity/Traits/MultiTenantTrait.php index 1e3b755df..f05310a44 100644 --- a/src/Entity/Traits/MultiTenantTrait.php +++ b/src/Entity/Traits/MultiTenantTrait.php @@ -11,7 +11,7 @@ trait MultiTenantTrait { /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\ManyToMany(targetEntity: Tenant::class)] private Collection $tenants; diff --git a/src/Entity/User.php b/src/Entity/User.php index c19a783c3..6f5b191a9 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -40,7 +40,7 @@ class User extends AbstractBaseEntity implements UserInterface, PasswordAuthenti private string $password = ''; /** - * @var \Doctrine\Common\Collections\Collection + * @var Collection */ #[ORM\OneToMany(targetEntity: UserRoleTenant::class, mappedBy: 'user', cascade: ['persist', 'remove'], orphanRemoval: true)] private Collection $userRoleTenants; diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 66b0f96e3..4e6d81760 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -100,7 +100,7 @@ private function parseBrndBooking(array $booking): array try { // Trim starttime to 6 digits after dot for microseconds $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); - $dateOnly = substr($booking['dato'], 0, 10); + $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$startTimeString; $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); if (false === $startDateTime) { @@ -116,7 +116,7 @@ private function parseBrndBooking(array $booking): array if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { try { $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); - $dateOnly = substr($booking['dato'], 0, 10); + $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$endTimeString; $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); if (false === $endDateTime) { diff --git a/src/Feed/SourceType/Brnd/ApiClient.php b/src/Feed/SourceType/Brnd/ApiClient.php index 147a58b8e..8d804f8da 100644 --- a/src/Feed/SourceType/Brnd/ApiClient.php +++ b/src/Feed/SourceType/Brnd/ApiClient.php @@ -86,9 +86,9 @@ private function getInfomonitorBookingsDetailsData( ): ResponseInterface { $secrets = new SecretsDTO($feedSource); $defaultStatusCodes = [self::STATUS_ALLOCATED]; - $date = $date ?? date('Y-m-d'); - $startTime = $startTime ?? ''; - $endTime = $endTime ?? ''; + $date ??= date('Y-m-d'); + $startTime ??= ''; + $endTime ??= ''; $bookingStatusCodes = implode(',', $bookingStatusCodes ?? $defaultStatusCodes); try { From 1febce1749248fad0f8789e3f83073bdb3f60432 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 25 Nov 2025 12:36:08 +0100 Subject: [PATCH 28/47] Add timezone support for booking date parsing in BrndFeedType --- src/Feed/BrndFeedType.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 66b0f96e3..625f29988 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -12,6 +12,7 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; +use DateTimeZone; /** * Brnd Bookingsystem Feed. @@ -94,6 +95,7 @@ public function getData(Feed $feed): array private function parseBrndBooking(array $booking): array { + $tz = new \DateTimeZone('Europe/Copenhagen'); // Parse start time $startDateTime = null; if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { @@ -102,7 +104,7 @@ private function parseBrndBooking(array $booking): array $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); $dateOnly = substr($booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$startTimeString; - $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); if (false === $startDateTime) { $startDateTime = null; } @@ -118,7 +120,7 @@ private function parseBrndBooking(array $booking): array $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); $dateOnly = substr($booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$endTimeString; - $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString); + $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); if (false === $endDateTime) { $endDateTime = null; } From d1ad65b287b14d8db8c1a719abfefd21f455db37 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 25 Nov 2025 13:42:54 +0100 Subject: [PATCH 29/47] Add BRND booking bug fix to changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 552027526..fa33d5ac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- [#333](https://github.com/os2display/display-api-service/pull/333) + - Add BRND booking feed type - [#313](https://github.com/os2display/display-api-service/pull/313) - Add BRND booking feed type From d7a527a4f80626e932905fdbd045890abbdbdf38 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 25 Nov 2025 13:44:35 +0100 Subject: [PATCH 30/47] Fix entry in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa33d5ac7..4d93d68d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - [#333](https://github.com/os2display/display-api-service/pull/333) - - Add BRND booking feed type + - Fix date parsing issue in BRND booking feed type - [#313](https://github.com/os2display/display-api-service/pull/313) - Add BRND booking feed type From c922996bd00d011b5b8eae9879d7b9d2678d2a30 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Tue, 25 Nov 2025 13:50:32 +0100 Subject: [PATCH 31/47] Remove unused DateTimeZone import from BrndFeedType --- src/Feed/BrndFeedType.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 625f29988..a0e4b15b1 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -12,7 +12,6 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Request; -use DateTimeZone; /** * Brnd Bookingsystem Feed. From 2c09859076e7a10c58fc7f907d7bc8a6e2e95e93 Mon Sep 17 00:00:00 2001 From: agnetemoos Date: Thu, 27 Nov 2025 11:03:55 +0100 Subject: [PATCH 32/47] Update src/Feed/BrndFeedType.php That is a fine idea. I just dont have time to do it before thursday or friday next week. Co-authored-by: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> --- src/Feed/BrndFeedType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index a0e4b15b1..bafec2bd1 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -94,7 +94,7 @@ public function getData(Feed $feed): array private function parseBrndBooking(array $booking): array { - $tz = new \DateTimeZone('Europe/Copenhagen'); + $tz = new \DateTimeZone(self::BRND_API_TIMEZONE); // Parse start time $startDateTime = null; if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { From fedc2644a1ab452204e6e109ef27f4f2ba228902 Mon Sep 17 00:00:00 2001 From: Agnete Moos Date: Fri, 5 Dec 2025 13:03:45 +0100 Subject: [PATCH 33/47] Refactor timezone handling in BrndFeedType to use a constant for BRND API timezone --- src/Feed/BrndFeedType.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index bafec2bd1..b0dfd1b7c 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -24,6 +24,11 @@ class BrndFeedType implements FeedTypeInterface final public const string SUPPORTED_FEED_TYPE = FeedOutputModels::BRND_BOOKING_OUTPUT; + /** + * BRND api datetime values are always given as 'Europe/Copenhagen'. + */ + private const string BRND_API_TIMEZONE = 'Europe/Copenhagen'; + public function __construct( private readonly FeedService $feedService, private readonly ApiClient $apiClient, From 98a079e06317a4b957ef5604dbf6ce26c5a3e399 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 5 Dec 2025 14:06:34 +0100 Subject: [PATCH 34/47] 5740: Updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdcce2ead..3d48b7f46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.6.0] - 2025-12-05 + - [#330](https://github.com/os2display/display-api-service/pull/330) - Composer update. - [#333](https://github.com/os2display/display-api-service/pull/333) From 59fa91b0971a726f83f0ac60000caa4ae7f6cbda Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Feb 2026 20:16:38 +0100 Subject: [PATCH 35/47] 6592: Add onFlush listener and tests for ManyToMany checksum propagation Add onFlush handler to detect ManyToMany collection changes that preUpdate misses, ensuring checksums propagate correctly. Add tests for add/remove on ScreenGroup.screens and Slide.media, plus upward propagation through the entity tree. Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 2 + .../RelationsChecksumListener.php | 48 ++++++- .../RelationsChecksumListenerTest.php | 131 ++++++++++++++++++ 3 files changed, 179 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d48b7f46..08aa9a67e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- Added onFlush listener to handle ManyToMany collection changes for relations checksum propagation. + ## [2.6.0] - 2025-12-05 - [#330](https://github.com/os2display/display-api-service/pull/330) diff --git a/src/EventListener/RelationsChecksumListener.php b/src/EventListener/RelationsChecksumListener.php index f822c8109..0e7ce834e 100644 --- a/src/EventListener/RelationsChecksumListener.php +++ b/src/EventListener/RelationsChecksumListener.php @@ -19,6 +19,7 @@ use App\Entity\Tenant\ScreenGroupCampaign; use App\Entity\Tenant\Slide; use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener; +use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PostFlushEventArgs; use Doctrine\ORM\Event\PrePersistEventArgs; use Doctrine\ORM\Event\PreRemoveEventArgs; @@ -53,6 +54,7 @@ #[AsDoctrineListener(event: Events::prePersist, priority: 100)] #[AsDoctrineListener(event: Events::preUpdate)] #[AsDoctrineListener(event: Events::preRemove)] +#[AsDoctrineListener(event: Events::onFlush)] #[AsDoctrineListener(event: Events::postFlush)] class RelationsChecksumListener { @@ -69,6 +71,7 @@ class RelationsChecksumListener * function to work. If the field is left as null it will be serialized to the * database as `[]` preventing JSON_SET from updating the field. * + * @param PrePersistEventArgs $args * @return void */ final public function prePersist(PrePersistEventArgs $args): void @@ -158,6 +161,7 @@ final public function prePersist(PrePersistEventArgs $args): void * * On update set "changed" to "true" to ensure checksum changes propagate up the tree. * + * @param PreUpdateEventArgs $args * @return void */ final public function preUpdate(PreUpdateEventArgs $args): void @@ -172,10 +176,11 @@ final public function preUpdate(PreUpdateEventArgs $args): void /** * PreRemove listener. * - * For "toMany" relations the "preUpdate" listener will not be called for the parent if a child relations - * is deleted by calling remove() on the entity manager. We need to manually set "changed" on the parent + * For "toMany" relations the "preUpdate" listener will not be called for the parent if child relations + * are deleted by calling remove() on the entity manager. We need to manually set "changed" on the parent * to "true" to ensure checksum changes propagate up the tree. * + * @param PreRemoveEventArgs $args * @return void */ final public function preRemove(PreRemoveEventArgs $args): void @@ -214,6 +219,45 @@ final public function preRemove(PreRemoveEventArgs $args): void } } + /** + * OnFlush listener. + * + * This listener is used to set the "changed" flag on entities that have been modified since the last flush. + * This is required because Doctrine does not call the "preUpdate" listener for entities that only have + * collection changes. + * + * @param OnFlushEventArgs $args + * @return void + */ + final public function onFlush(OnFlushEventArgs $args): void + { + $em = $args->getObjectManager(); + $uow = $em->getUnitOfWork(); + + // Catch ManyToMany collection adds/removes + foreach ($uow->getScheduledCollectionUpdates() as $collection) { + $owner = $collection->getOwner(); + if ($owner instanceof RelationsChecksumInterface) { + $owner->setChanged(true); + $uow->recomputeSingleEntityChangeSet( + $em->getClassMetadata($owner::class), + $owner + ); + } + } + + foreach ($uow->getScheduledCollectionDeletions() as $collection) { + $owner = $collection->getOwner(); + if ($owner instanceof RelationsChecksumInterface) { + $owner->setChanged(true); + $uow->recomputeSingleEntityChangeSet( + $em->getClassMetadata($owner::class), + $owner + ); + } + } + } + /** * PostFlush listener. * diff --git a/tests/EventListener/RelationsChecksumListenerTest.php b/tests/EventListener/RelationsChecksumListenerTest.php index c94aa6154..3d6ad19ee 100644 --- a/tests/EventListener/RelationsChecksumListenerTest.php +++ b/tests/EventListener/RelationsChecksumListenerTest.php @@ -478,6 +478,137 @@ public function testPersistScreen(): void $this->assertFalse($playlistScreenRegion->isChanged()); } + public function testAddScreenToScreenGroupUpdatesChecksum(): void + { + $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); + /** @var Tenant\ScreenGroup $screenGroup */ + $screenGroup = $this->em->getRepository(Tenant\ScreenGroup::class)->findOneBy(['tenant' => $tenant]); + $beforeChecksum = $screenGroup->getRelationsChecksum()['screens']; + + // Create a new screen to add + $screenLayout = $this->em->getRepository(ScreenLayout::class)->findOneBy(['title' => 'Full screen']); + $screen = new Tenant\Screen(); + $screen->setTenant($tenant); + $screen->setScreenLayout($screenLayout); + $screen->setCreatedBy(self::class.'::testAddScreenToScreenGroupUpdatesChecksum()'); + + $this->em->persist($screen); + $this->em->flush(); + + // Collection-only change on screen group — no scalar property change + $screenGroup->addScreen($screen); + $this->em->flush(); + + $this->em->refresh($screenGroup); + $this->assertNotEquals($beforeChecksum, $screenGroup->getRelationsChecksum()['screens']); + $this->assertFalse($screenGroup->isChanged()); + } + + public function testRemoveScreenFromScreenGroupUpdatesChecksum(): void + { + $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); + /** @var Tenant\ScreenGroup $screenGroup */ + $screenGroup = $this->em->getRepository(Tenant\ScreenGroup::class)->findOneBy(['tenant' => $tenant]); + $this->assertGreaterThan(0, $screenGroup->getScreens()->count()); + + $beforeChecksum = $screenGroup->getRelationsChecksum()['screens']; + + // Collection-only change — remove a screen without changing scalar properties + $screen = $screenGroup->getScreens()->first(); + $screenGroup->removeScreen($screen); + $this->em->flush(); + + $this->em->refresh($screenGroup); + $this->assertNotEquals($beforeChecksum, $screenGroup->getRelationsChecksum()['screens']); + $this->assertFalse($screenGroup->isChanged()); + } + + public function testAddMediaToSlideUpdatesChecksum(): void + { + $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); + /** @var Tenant\Slide $slide */ + $slide = $this->em->getRepository(Tenant\Slide::class)->findOneBy(['tenant' => $tenant]); + $beforeChecksum = $slide->getRelationsChecksum()['media']; + + // Find a media not already on this slide + $allMedia = $this->em->getRepository(Tenant\Media::class)->findBy(['tenant' => $tenant]); + $existingMediaIds = $slide->getMedia()->map(fn ($m) => $m->getId())->toArray(); + $newMedia = null; + foreach ($allMedia as $candidate) { + if (!in_array($candidate->getId(), $existingMediaIds, true)) { + $newMedia = $candidate; + break; + } + } + $this->assertNotNull($newMedia, 'No available media found for test'); + + // Collection-only change on slide — no scalar property change + $slide->addMedium($newMedia); + $this->em->flush(); + + $this->em->refresh($slide); + $this->assertNotEquals($beforeChecksum, $slide->getRelationsChecksum()['media']); + $this->assertFalse($slide->isChanged()); + } + + public function testRemoveMediaFromSlideUpdatesChecksum(): void + { + $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); + /** @var Tenant\Slide $slide */ + $slide = $this->em->getRepository(Tenant\Slide::class)->findOneBy(['tenant' => $tenant]); + $this->assertGreaterThan(0, $slide->getMedia()->count()); + + $beforeChecksum = $slide->getRelationsChecksum()['media']; + + // Collection-only change — remove media without changing scalar properties + $media = $slide->getMedia()->first(); + $slide->removeMedium($media); + $this->em->flush(); + + $this->em->refresh($slide); + $this->assertNotEquals($beforeChecksum, $slide->getRelationsChecksum()['media']); + $this->assertFalse($slide->isChanged()); + } + + public function testManyToManyChangePropagatesUpTree(): void + { + $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); + + /** @var Tenant\ScreenGroup $screenGroup */ + $screenGroup = $this->em->getRepository(Tenant\ScreenGroup::class)->findOneBy(['tenant' => $tenant]); + $screenGroupBefore = $screenGroup->getRelationsChecksum()['screens']; + + // Get a screen that belongs to this group — its inScreenGroups checksum should also change + /** @var Tenant\Screen $existingScreen */ + $existingScreen = $screenGroup->getScreens()->first(); + $this->assertNotNull($existingScreen); + $screenBefore = $existingScreen->getRelationsChecksum()['inScreenGroups']; + + // Create a new screen to add to the group + $screenLayout = $this->em->getRepository(ScreenLayout::class)->findOneBy(['title' => 'Full screen']); + $newScreen = new Tenant\Screen(); + $newScreen->setTenant($tenant); + $newScreen->setScreenLayout($screenLayout); + $newScreen->setCreatedBy(self::class.'::testManyToManyChangePropagatesUpTree()'); + + $this->em->persist($newScreen); + $this->em->flush(); + + // Collection-only change on screen group — triggers onFlush + $screenGroup->addScreen($newScreen); + $this->em->flush(); + + // Screen group checksum should update + $this->em->refresh($screenGroup); + $this->assertNotEquals($screenGroupBefore, $screenGroup->getRelationsChecksum()['screens']); + $this->assertFalse($screenGroup->isChanged()); + + // Existing screen's inScreenGroups checksum should propagate + $this->em->refresh($existingScreen); + $this->assertNotEquals($screenBefore, $existingScreen->getRelationsChecksum()['inScreenGroups']); + $this->assertFalse($existingScreen->isChanged()); + } + public function testPlaylistSlideRelation(): void { $tenant = $this->em->getRepository(Tenant::class)->findOneBy(['tenantKey' => 'ABC']); From b3a7c36eb9db2deb0f640ee9a9b9a63b7753b582 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Feb 2026 20:21:41 +0100 Subject: [PATCH 36/47] 6592: Add PR link to changelog Co-Authored-By: Claude Opus 4.6 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08aa9a67e..b5e92347c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- Added onFlush listener to handle ManyToMany collection changes for relations checksum propagation. +- [#347](https://github.com/os2display/display-api-service/pull/347) + - Added onFlush listener to handle ManyToMany collection changes for relations checksum propagation. ## [2.6.0] - 2025-12-05 From 09d3b1b8a4e97cd579f77777a35801426fae3c03 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Wed, 25 Feb 2026 20:25:50 +0100 Subject: [PATCH 37/47] 6592: Fix PHP CS fixer violations in docblocks Co-Authored-By: Claude Opus 4.6 --- src/EventListener/RelationsChecksumListener.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/EventListener/RelationsChecksumListener.php b/src/EventListener/RelationsChecksumListener.php index 0e7ce834e..f361fe4f6 100644 --- a/src/EventListener/RelationsChecksumListener.php +++ b/src/EventListener/RelationsChecksumListener.php @@ -72,6 +72,7 @@ class RelationsChecksumListener * database as `[]` preventing JSON_SET from updating the field. * * @param PrePersistEventArgs $args + * * @return void */ final public function prePersist(PrePersistEventArgs $args): void @@ -162,6 +163,7 @@ final public function prePersist(PrePersistEventArgs $args): void * On update set "changed" to "true" to ensure checksum changes propagate up the tree. * * @param PreUpdateEventArgs $args + * * @return void */ final public function preUpdate(PreUpdateEventArgs $args): void @@ -181,6 +183,7 @@ final public function preUpdate(PreUpdateEventArgs $args): void * to "true" to ensure checksum changes propagate up the tree. * * @param PreRemoveEventArgs $args + * * @return void */ final public function preRemove(PreRemoveEventArgs $args): void @@ -227,6 +230,7 @@ final public function preRemove(PreRemoveEventArgs $args): void * collection changes. * * @param OnFlushEventArgs $args + * * @return void */ final public function onFlush(OnFlushEventArgs $args): void From 991cf7e38ef9ac09183c88fad7c13f5857c6504b Mon Sep 17 00:00:00 2001 From: "LAPTOP-RSOLLPLO\\sl" Date: Thu, 26 Feb 2026 09:58:43 +0100 Subject: [PATCH 38/47] Fix: Use correct BRND field names --- src/Feed/BrndFeedType.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 098c0126b..48d568eef 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -102,10 +102,10 @@ private function parseBrndBooking(array $booking): array $tz = new \DateTimeZone(self::BRND_API_TIMEZONE); // Parse start time $startDateTime = null; - if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { + if (!empty($booking['dato']) && isset($booking['starttId']) && is_string($booking['starttId'])) { try { // Trim starttime to 6 digits after dot for microseconds - $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); + $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttId']); $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$startTimeString; $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); @@ -119,9 +119,9 @@ private function parseBrndBooking(array $booking): array // Parse end time $endDateTime = null; - if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { + if (!empty($booking['dato']) && isset($booking['sluttId']) && is_string($booking['sluttId'])) { try { - $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); + $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttId']); $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$endTimeString; $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); @@ -144,8 +144,8 @@ private function parseBrndBooking(array $booking): array 'activity' => $booking['aktivitet'] ?? '', 'team' => $booking['hold'] ?? '', 'status' => $booking['status'] ?? '', - 'checkIn' => $booking['checK_IN'] ?? '', - 'bookingBy' => $booking['ansøgt_af'] ?? '', + 'checkIn' => $booking['checkIN'] ?? '', + 'bookingBy' => $booking['ansøgtAF'] ?? '', 'changingRooms' => $booking['omklædningsrum'] ?? '', ]; } From bff0cafea573cf7ec3b25dad01419a3c01a2cabf Mon Sep 17 00:00:00 2001 From: "LAPTOP-RSOLLPLO\\sl" Date: Thu, 26 Feb 2026 10:56:47 +0100 Subject: [PATCH 39/47] Revert "Fix: Use correct BRND field names" This reverts commit 991cf7e38ef9ac09183c88fad7c13f5857c6504b. --- src/Feed/BrndFeedType.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Feed/BrndFeedType.php b/src/Feed/BrndFeedType.php index 48d568eef..098c0126b 100644 --- a/src/Feed/BrndFeedType.php +++ b/src/Feed/BrndFeedType.php @@ -102,10 +102,10 @@ private function parseBrndBooking(array $booking): array $tz = new \DateTimeZone(self::BRND_API_TIMEZONE); // Parse start time $startDateTime = null; - if (!empty($booking['dato']) && isset($booking['starttId']) && is_string($booking['starttId'])) { + if (!empty($booking['dato']) && isset($booking['starttid']) && is_string($booking['starttid'])) { try { // Trim starttime to 6 digits after dot for microseconds - $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttId']); + $startTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['starttid']); $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$startTimeString; $startDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); @@ -119,9 +119,9 @@ private function parseBrndBooking(array $booking): array // Parse end time $endDateTime = null; - if (!empty($booking['dato']) && isset($booking['sluttId']) && is_string($booking['sluttId'])) { + if (!empty($booking['dato']) && isset($booking['sluttid']) && is_string($booking['sluttid'])) { try { - $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttId']); + $endTimeString = preg_replace('/\.(\d{6})\d+$/', '.$1', $booking['sluttid']); $dateOnly = substr((string) $booking['dato'], 0, 10); $dateTimeString = $dateOnly.' '.$endTimeString; $endDateTime = \DateTimeImmutable::createFromFormat('m/d/Y H:i:s.u', $dateTimeString, $tz); @@ -144,8 +144,8 @@ private function parseBrndBooking(array $booking): array 'activity' => $booking['aktivitet'] ?? '', 'team' => $booking['hold'] ?? '', 'status' => $booking['status'] ?? '', - 'checkIn' => $booking['checkIN'] ?? '', - 'bookingBy' => $booking['ansøgtAF'] ?? '', + 'checkIn' => $booking['checK_IN'] ?? '', + 'bookingBy' => $booking['ansøgt_af'] ?? '', 'changingRooms' => $booking['omklædningsrum'] ?? '', ]; } From 87f14ccbfc9b8aa9fea5aec1e470950d3e3cfe21 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Feb 2026 09:07:04 +0100 Subject: [PATCH 40/47] Add checksum recalculation command and extract calculator service Extract SQL generation and execution logic from RelationsChecksumListener into a dedicated RelationsChecksumCalculator service. Add a new console command (app:checksum:recalculate) to trigger checksum recalculation for slides and media with optional --tenant and --modified-after filters. Co-Authored-By: Claude Opus 4.6 --- .../Checksum/RecalculateChecksumCommand.php | 154 +++++++++ .../Loader/DoctrineOrmLoaderDecorator.php | 16 +- .../RelationsChecksumListener.php | 304 +----------------- src/Service/RelationsChecksumCalculator.php | 287 +++++++++++++++++ 4 files changed, 451 insertions(+), 310 deletions(-) create mode 100644 src/Command/Checksum/RecalculateChecksumCommand.php create mode 100644 src/Service/RelationsChecksumCalculator.php diff --git a/src/Command/Checksum/RecalculateChecksumCommand.php b/src/Command/Checksum/RecalculateChecksumCommand.php new file mode 100644 index 000000000..f1d1f789b --- /dev/null +++ b/src/Command/Checksum/RecalculateChecksumCommand.php @@ -0,0 +1,154 @@ +addOption(self::OPTION_TENANT, null, InputOption::VALUE_REQUIRED, 'Filter by tenant key') + ->addOption(self::OPTION_MODIFIED_AFTER, null, InputOption::VALUE_REQUIRED, 'Filter by modified_at >= date (e.g. "2024-01-01" or "2024-01-01 12:00:00")') + ->setHelp(<<<'HELP' +The %command.name% command recalculates relation checksums for slides and media, +then propagates the changes up the entity tree. + + php %command.full_name% + +You can filter by tenant key and/or modification date: + + php %command.full_name% --tenant=ABC + php %command.full_name% --modified-after="2024-01-01" + php %command.full_name% --tenant=ABC --modified-after="2024-01-01 12:00:00" + +Without any filters, all slides and media will be recalculated. +HELP) + ; + } + + public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void + { + if ($input->mustSuggestOptionValuesFor(self::OPTION_TENANT)) { + $tenants = $this->tenantRepository->findAll(); + foreach ($tenants as $tenant) { + $suggestions->suggestValue($tenant->getTenantKey()); + } + } + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $io = new SymfonyStyle($input, $output); + $stopwatch = new Stopwatch(); + $stopwatch->start('checksum-recalculate'); + + $tenantKey = $input->getOption(self::OPTION_TENANT); + $modifiedAfterStr = $input->getOption(self::OPTION_MODIFIED_AFTER); + + // Resolve tenant + $tenant = null; + if (null !== $tenantKey) { + $tenant = $this->tenantRepository->findOneBy(['tenantKey' => $tenantKey]); + if (null === $tenant) { + $io->error(sprintf('Tenant with key "%s" not found.', $tenantKey)); + + return Command::FAILURE; + } + $io->info(sprintf('Filtering by tenant: %s', $tenantKey)); + } + + // Parse date + $modifiedAfter = null; + if (null !== $modifiedAfterStr) { + try { + $modifiedAfter = new \DateTimeImmutable($modifiedAfterStr); + } catch (\Exception) { + $io->error(sprintf('Invalid date format: "%s". Use formats like "Y-m-d" or "Y-m-d H:i:s".', $modifiedAfterStr)); + + return Command::FAILURE; + } + $io->info(sprintf('Filtering by modified after: %s', $modifiedAfter->format('Y-m-d H:i:s'))); + } + + // Mark matching slides and media as changed using DQL UPDATE + $targetEntities = [ + 'slide' => Slide::class, + 'media' => Media::class, + ]; + $totalAffected = 0; + + foreach ($targetEntities as $label => $entityClass) { + $qb = $this->entityManager->createQueryBuilder() + ->update($entityClass, 'e') + ->set('e.changed', ':changed') + ->setParameter('changed', true); + + if (null !== $tenant) { + $qb->andWhere('e.tenant = :tenant') + ->setParameter('tenant', $tenant); + } + + if (null !== $modifiedAfter) { + $qb->andWhere('e.modifiedAt >= :modifiedAfter') + ->setParameter('modifiedAfter', $modifiedAfter); + } + + $affected = $qb->getQuery()->execute(); + $totalAffected += $affected; + $io->info(sprintf('Marked %d rows in "%s" as changed.', $affected, $label)); + } + + if (0 === $totalAffected) { + $io->warning('No rows matched the given filters. Nothing to recalculate.'); + + return Command::SUCCESS; + } + + // Propagate checksums through entity tree + $io->info('Propagating checksums through entity tree...'); + $this->calculator->execute(withWhereClause: true); + + $event = $stopwatch->stop('checksum-recalculate'); + + $io->success(sprintf( + 'Checksums recalculated. %d rows marked. Elapsed: %.2f ms, Memory: %.2f MB', + $totalAffected, + $event->getDuration(), + $event->getMemory() / (1024 ** 2) + )); + + return Command::SUCCESS; + } +} diff --git a/src/DataFixtures/Loader/DoctrineOrmLoaderDecorator.php b/src/DataFixtures/Loader/DoctrineOrmLoaderDecorator.php index 3ae0f3e8e..f95bef641 100644 --- a/src/DataFixtures/Loader/DoctrineOrmLoaderDecorator.php +++ b/src/DataFixtures/Loader/DoctrineOrmLoaderDecorator.php @@ -6,6 +6,7 @@ use App\EventListener\RelationsChecksumListener; use App\EventListener\TimestampableListener; +use App\Service\RelationsChecksumCalculator; use Doctrine\ORM\EntityManagerInterface; use Hautelook\AliceBundle\Loader\DoctrineOrmLoader; use Hautelook\AliceBundle\LoaderInterface as AliceBundleLoaderInterface; @@ -28,6 +29,7 @@ class DoctrineOrmLoaderDecorator implements AliceBundleLoaderInterface, LoggerAw { public function __construct( private readonly DoctrineOrmLoader $decorated, + private readonly RelationsChecksumCalculator $calculator, ) {} public function load(Application $application, EntityManagerInterface $manager, array $bundles, string $environment, bool $append, bool $purgeWithTruncate, bool $noBundles = false): array @@ -59,7 +61,7 @@ public function load(Application $application, EntityManagerInterface $manager, $result = $this->decorated->load($application, $manager, $bundles, $environment, $append, $purgeWithTruncate, $noBundles); // Apply the SQL statements from the disabled "postFlush" listener - $this->applyRelationsModified($manager); + $this->applyRelationsModified(); // Re-enable listeners $eventManager->addEventListener('postFlush', $relationsModifiedAtListener); @@ -77,16 +79,8 @@ public function withLogger(LoggerInterface $logger): static $this->decorated->withLogger($logger); } - private function applyRelationsModified(EntityManagerInterface $manager): void + private function applyRelationsModified(): void { - $connection = $manager->getConnection(); - - $sqlQueries = RelationsChecksumListener::getUpdateRelationsAtQueries(withWhereClause: false); - - $rows = 0; - foreach ($sqlQueries as $sqlQuery) { - $stm = $connection->prepare($sqlQuery); - $rows += $stm->executeStatement(); - } + $this->calculator->execute(withWhereClause: false); } } diff --git a/src/EventListener/RelationsChecksumListener.php b/src/EventListener/RelationsChecksumListener.php index f361fe4f6..66d67801a 100644 --- a/src/EventListener/RelationsChecksumListener.php +++ b/src/EventListener/RelationsChecksumListener.php @@ -18,6 +18,7 @@ use App\Entity\Tenant\ScreenGroup; use App\Entity\Tenant\ScreenGroupCampaign; use App\Entity\Tenant\Slide; +use App\Service\RelationsChecksumCalculator; use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener; use Doctrine\ORM\Event\OnFlushEventArgs; use Doctrine\ORM\Event\PostFlushEventArgs; @@ -58,9 +59,9 @@ #[AsDoctrineListener(event: Events::postFlush)] class RelationsChecksumListener { - private const array CHECKSUM_TABLES = ['feed_source', 'feed', 'slide', 'media', 'theme', 'template', 'playlist_slide', - 'playlist', 'screen_campaign', 'screen', 'screen_group_campaign', 'screen_group', - 'playlist_screen_region', 'screen_layout_regions', 'screen_layout']; + public function __construct( + private readonly RelationsChecksumCalculator $calculator, + ) {} /** * PrePersist listener. @@ -275,301 +276,6 @@ final public function onFlush(OnFlushEventArgs $args): void */ final public function postFlush(PostFlushEventArgs $args): void { - $connection = $args->getObjectManager()->getConnection(); - - $sqlQueries = self::getUpdateRelationsAtQueries(withWhereClause: true); - - $connection->beginTransaction(); - - try { - foreach ($sqlQueries as $sqlQuery) { - $stm = $connection->prepare($sqlQuery); - $stm->executeStatement(); - } - - $connection->commit(); - } catch (\Exception $e) { - $connection->rollBack(); - throw $e; - } - } - - /** - * Get an array of SQL update statements to update the changed and relationsModified fields. - * - * @param bool $withWhereClause - * Should the statements include a where clause to limit the statement - * - * @return string[] - * Array of SQL statements - */ - public static function getUpdateRelationsAtQueries(bool $withWhereClause = true): array - { - // Set SQL update queries for the "relations checksum" fields on the parent (p), child (c) relationships up through the entity tree - $sqlQueries = []; - - // Feed - $sqlQueries[] = self::getToOneQuery(jsonKey: 'feedSource', parentTable: 'feed', childTable: 'feed_source', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'slide', parentTable: 'feed', childTable: 'slide', parentTableId: 'id', childTableId: 'feed_id', withWhereClause: $withWhereClause); - - // Slide - $sqlQueries[] = self::getManyToManyQuery(jsonKey: 'media', parentTable: 'slide', pivotTable: 'slide_media', childTable: 'media', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'theme', parentTable: 'slide', childTable: 'theme', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'templateInfo', parentTable: 'slide', childTable: 'template', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'feed', parentTable: 'slide', childTable: 'feed', withWhereClause: $withWhereClause); - - // PlaylistSlide - $sqlQueries[] = self::getToOneQuery(jsonKey: 'slide', parentTable: 'playlist_slide', childTable: 'slide', withWhereClause: $withWhereClause); - - // Playlist - $sqlQueries[] = self::getOneToManyQuery(jsonKey: 'slides', parentTable: 'playlist', childTable: 'playlist_slide', withWhereClause: $withWhereClause); - - // ScreenCampaign - $sqlQueries[] = self::getToOneQuery(jsonKey: 'campaign', parentTable: 'screen_campaign', childTable: 'playlist', parentTableId: 'campaign_id', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'screen', parentTable: 'screen_campaign', childTable: 'screen', withWhereClause: $withWhereClause); - - // ScreenGroupCampaign - campaign - $sqlQueries[] = self::getToOneQuery(jsonKey: 'campaign', parentTable: 'screen_group_campaign', childTable: 'playlist', parentTableId: 'campaign_id', withWhereClause: $withWhereClause); - - // ScreenGroup - $sqlQueries[] = self::getManyToManyQuery(jsonKey: 'screens', parentTable: 'screen_group', pivotTable: 'screen_group_screen', childTable: 'screen', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getOneToManyQuery(jsonKey: 'screenGroupCampaigns', parentTable: 'screen_group', childTable: 'screen_group_campaign', withWhereClause: $withWhereClause); - - // ScreenGroupCampaign - screenGroup - $sqlQueries[] = self::getToOneQuery(jsonKey: 'screenGroup', parentTable: 'screen_group_campaign', childTable: 'screen_group', withWhereClause: $withWhereClause); - - // PlaylistScreenRegion - $sqlQueries[] = self::getToOneQuery(jsonKey: 'playlist', parentTable: 'playlist_screen_region', childTable: 'playlist', withWhereClause: $withWhereClause); - - // ScreenLayoutRegions - $sqlQueries[] = self::getToOneQuery(jsonKey: 'regions', parentTable: 'screen_layout_regions', childTable: 'playlist_screen_region', parentTableId: 'id', childTableId: 'region_id', withWhereClause: $withWhereClause); - - // ScreenLayout - $sqlQueries[] = self::getOneToManyQuery(jsonKey: 'regions', parentTable: 'screen_layout', childTable: 'screen_layout_regions', withWhereClause: $withWhereClause); - - // Screen - $sqlQueries[] = self::getOneToManyQuery(jsonKey: 'campaigns', parentTable: 'screen', childTable: 'screen_campaign', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getToOneQuery(jsonKey: 'layout', parentTable: 'screen', childTable: 'screen_layout', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getOneToManyQuery(jsonKey: 'regions', parentTable: 'screen', childTable: 'playlist_screen_region', withWhereClause: $withWhereClause); - $sqlQueries[] = self::getManyToManyQuery(jsonKey: 'inScreenGroups', parentTable: 'screen', pivotTable: 'screen_group_screen', childTable: 'screen_group', withWhereClause: $withWhereClause); - - // Add reset 'changed' fields queries - $sqlQueries = array_merge($sqlQueries, self::getResetChangedQueries()); - - return $sqlQueries; - } - - /** - * Get "One/ManyToOne" query. - * - * For a table (parent) that has a relation to another table (child) where we need to update the "relations_checksum" - * field on the parent with a checksum of values from the child we need to join the tables and set the values. - * - * Basically we do: "Update parent, join child, set parent value = SHA(child values)" - * - * Example: - * UPDATE slide p - * INNER JOIN theme c ON p.theme_id = c.id - * SET p.changed = 1, - * p.relations_checksum = JSON_SET(p.relations_checksum, "$.theme", SHA1(CONCAT(c.id, c.version, c.relations_checksum))) - * WHERE - * p.changed = 1 - * OR c.changed = 1 - * - * Explanation: - * UPDATE parent table p, INNER JOIN child table c - * - use INNER JOIN because the query only makes sense for result where both parent and child tables have rows - * SET changed to 1 (true) to enable propagation up the tree. - * SET the value for the relevant json key on the json object in p.relations_checksum to the checksum of the child id, version and relations checksum - * WHERE either p.changed or c.changed is true - * - Because we can't easily get a list of ID's of affected rows as we work up the tree we use the bool "changed" as clause in WHERE to limit to only update the rows just modified. - * - * @param string|null $parentTableId - * - * @return string - */ - private static function getToOneQuery(string $jsonKey, string $parentTable, string $childTable, ?string $parentTableId = null, string $childTableId = 'id', bool $withWhereClause = true): string - { - // Set the column name to use for "ON" in the Join clause. By default, the child table name with "_id" appended. - // E.g. "UPDATE feed p INNER JOIN feed_source c ON p.feed_source_id = c.id" - $parentTableId ??= $childTable.'_id'; - - // The base UPDATE query. - // - Use INNER JON to only select rows that have a match in both parent and child tables - // - Use JSON_SET to only INSERT/UPDATE the relevant key in the json object, not the whole field. - $queryFormat = ' - UPDATE %s p - INNER JOIN %s c ON p.%s = c.%s - SET p.changed = 1, - p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", SHA1(CONCAT(c.id, c.version, c.relations_checksum))) - '; - - $query = sprintf($queryFormat, $parentTable, $childTable, $parentTableId, $childTableId, $jsonKey); - - // Add WHERE clause to only update rows that have been modified since ":modified_at" - if ($withWhereClause) { - $query .= ' WHERE p.changed = 1 OR c.changed = 1'; - } - - return $query; - } - - /** - * Get "OnetoMany" query. - * - * For a table (parent) that has a toMany relationship to another table (child) where we need to update the "relations_checksum" - * field on the parent with a checksum of values from the child we need to join the tables and set the values. - * - * Example: - * UPDATE - * playlist p - * INNER JOIN ( - * SELECT - * c.playlist_id, - * CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, - * SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum - * FROM - * playlist_slide c - * GROUP BY - * c.playlist_id - * ) temp ON p.id = temp.playlist_id - * SET p.changed = 1, - * p.relations_checksum = JSON_SET(p.relations_checksum, "$.slides", temp.checksum) - * WHERE p.changed = 1 OR temp.changed = 1 - * - * Explanation: - * Because this is a "to many" relation we need to GROUP_CONCAT values from the child relations. This is done in a temporary table - * with GROUP BY parent id in the child table. This gives us just one child row for each parent row with a checksum from the relevant - * fields across all child rows. We use a DISTINCT clause in GROUP_CONCAT to limit the length of the resulting value and avoid - * illegal integer values. - * - * This temp table is then joined to the parent table to allow us to SET the p.changed and p.relations_checksum values on the parent. - * - Because GROUP_CONCAT will give us all child rows "changed" as one, e.g. "00010001" we need "> 0" to evaluate to true/false - * and then CAST that to "unsigned" to get a TINYINT (bool) - * WHERE either p.changed or c.changed is true - * - Because we can't easily get a list of ID's of affected rows as we work up the tree we use the bool "changed" as clause in - * WHERE to limit to only update the rows just modified. - * - * @return string - */ - private static function getOneToManyQuery(string $jsonKey, string $parentTable, string $childTable, bool $withWhereClause = true): string - { - $parentTableId = $parentTable.'_id'; - - $queryFormat = ' - UPDATE - %s p - INNER JOIN ( - SELECT - c.%s, - CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, - SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum - FROM - %s c - GROUP BY - c.%s - ) temp ON p.id = temp.%s - SET p.changed = 1, - p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", temp.checksum) - '; - - $query = sprintf($queryFormat, $parentTable, $parentTableId, $childTable, $parentTableId, $parentTableId, $jsonKey); - - if ($withWhereClause) { - $query .= ' WHERE p.changed = 1 OR temp.changed = 1'; - } - - return $query; - } - - /** - * Get "many to many" query. - * - * For a table (parent) that has a relation to another table (child) through a pivot table where we need to update the "changed" - * and "relations_checksum" fields on the parent with values from the child we need to join the tables and set the values. - * - * Basically we do: - * "Update parent, join temp (SELECT checksum of c.id, c.version, c.relations_checksum from the child rows with GROUP_CONCAT), set parent values = child values" - * - * Example: - * UPDATE - * slide p - * INNER JOIN ( - * SELECT - * pivot.slide_id, - * CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, - * SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum - * FROM - * slide_media pivot - * INNER JOIN media c ON pivot.media_id = c.id - * GROUP BY - * pivot.slide_id - * ) temp ON p.id = temp.slide_id - * SET p.changed = 1, - * p.relations_checksum = JSON_SET(p.relations_checksum, "$.media", temp.checksum) - * WHERE p.changed = 1 OR temp.changed = 1 - * - * Explanation: - * Because this is a "to many" relation we need to GROUP_CONCAT values from the child relations. This is done in a temporary table - * with GROUP BY parent id in the child table. This gives us just one child row for each parent row with a checksum from the relevant - * fields across all child rows. We use a DISTINCT clause in GROUP_CONCAT to limit the length of the resulting value and avoid - * illegal integer values. - * - * This temp table is then joined to the parent table to allow us to SET the p.changed and p.relations_checksum values on the parent. - * - Because GROUP_CONCAT will give us all child rows "changed" as one, e.g. "00010001" we need "> 0" to evaluate to true/false - * and then CAST that to "unsigned" to get a TINYINT (bool) - * WHERE either p.changed or c.changed is true - * - Because we can't easily get a list of ID's of affected rows as we work up the tree we use the bool "changed" as clause in - * WHERE to limit to only update the rows just modified. - * - * @return string - */ - private static function getManyToManyQuery(string $jsonKey, string $parentTable, string $pivotTable, string $childTable, bool $withWhereClause = true): string - { - $parentTableId = $parentTable.'_id'; - $childTableId = $childTable.'_id'; - - $queryFormat = ' - UPDATE - %s p - INNER JOIN ( - SELECT - pivot.%s, - CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, - SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum - FROM - %s pivot - INNER JOIN %s c ON pivot.%s = c.id - GROUP BY - pivot.%s - ) temp ON p.id = temp.%s - SET p.changed = 1, - p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", temp.checksum) - '; - - $query = sprintf($queryFormat, $parentTable, $parentTableId, $pivotTable, $childTable, $childTableId, $parentTableId, $parentTableId, $jsonKey); - if ($withWhereClause) { - $query .= ' WHERE p.changed = 1 OR temp.changed = 1'; - } - - return $query; - } - - /** - * Get an array of queries to reset all "changed" fields to 0. - * - * Example: - * UPDATE screen SET screen.changed = 0 WHERE screen.changed = 1; - * - * @return array - */ - private static function getResetChangedQueries(): array - { - $queries = []; - foreach (self::CHECKSUM_TABLES as $table) { - $queries[] = sprintf('UPDATE %s SET changed = 0 WHERE changed = 1', $table); - } - - return $queries; + $this->calculator->execute(withWhereClause: true); } } diff --git a/src/Service/RelationsChecksumCalculator.php b/src/Service/RelationsChecksumCalculator.php new file mode 100644 index 000000000..2e76cf999 --- /dev/null +++ b/src/Service/RelationsChecksumCalculator.php @@ -0,0 +1,287 @@ + slide -> + * playlist_slide -> playlist -> screen). + * + * Extracted from RelationsChecksumListener to allow reuse in console commands + * and other contexts outside Doctrine lifecycle events. + */ +class RelationsChecksumCalculator +{ + public const array CHECKSUM_TABLES = ['feed_source', 'feed', 'slide', 'media', 'theme', 'template', 'playlist_slide', + 'playlist', 'screen_campaign', 'screen', 'screen_group_campaign', 'screen_group', + 'playlist_screen_region', 'screen_layout_regions', 'screen_layout']; + + public function __construct( + private readonly Connection $connection, + ) {} + + /** + * Execute all checksum propagation queries in a transaction. + * + * @param bool $withWhereClause limit updates to rows where changed = 1 + * + * @throws \Doctrine\DBAL\Exception + */ + public function execute(bool $withWhereClause = true): void + { + $sqlQueries = $this->getUpdateRelationsAtQueries(withWhereClause: $withWhereClause); + + $this->connection->beginTransaction(); + + try { + foreach ($sqlQueries as $sqlQuery) { + $stm = $this->connection->prepare($sqlQuery); + $stm->executeStatement(); + } + + $this->connection->commit(); + } catch (\Exception $e) { + $this->connection->rollBack(); + throw $e; + } + } + + /** + * Get an array of SQL update statements to update the changed and relationsModified fields. + * + * @param bool $withWhereClause + * Should the statements include a where clause to limit the statement + * + * @return string[] + * Array of SQL statements + */ + public function getUpdateRelationsAtQueries(bool $withWhereClause = true): array + { + // Set SQL update queries for the "relations checksum" fields on the parent (p), child (c) relationships up through the entity tree + $sqlQueries = []; + + // Feed + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'feedSource', parentTable: 'feed', childTable: 'feed_source', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'slide', parentTable: 'feed', childTable: 'slide', parentTableId: 'id', childTableId: 'feed_id', withWhereClause: $withWhereClause); + + // Slide + $sqlQueries[] = $this->getManyToManyQuery(jsonKey: 'media', parentTable: 'slide', pivotTable: 'slide_media', childTable: 'media', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'theme', parentTable: 'slide', childTable: 'theme', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'templateInfo', parentTable: 'slide', childTable: 'template', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'feed', parentTable: 'slide', childTable: 'feed', withWhereClause: $withWhereClause); + + // PlaylistSlide + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'slide', parentTable: 'playlist_slide', childTable: 'slide', withWhereClause: $withWhereClause); + + // Playlist + $sqlQueries[] = $this->getOneToManyQuery(jsonKey: 'slides', parentTable: 'playlist', childTable: 'playlist_slide', withWhereClause: $withWhereClause); + + // ScreenCampaign + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'campaign', parentTable: 'screen_campaign', childTable: 'playlist', parentTableId: 'campaign_id', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'screen', parentTable: 'screen_campaign', childTable: 'screen', withWhereClause: $withWhereClause); + + // ScreenGroupCampaign - campaign + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'campaign', parentTable: 'screen_group_campaign', childTable: 'playlist', parentTableId: 'campaign_id', withWhereClause: $withWhereClause); + + // ScreenGroup + $sqlQueries[] = $this->getManyToManyQuery(jsonKey: 'screens', parentTable: 'screen_group', pivotTable: 'screen_group_screen', childTable: 'screen', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getOneToManyQuery(jsonKey: 'screenGroupCampaigns', parentTable: 'screen_group', childTable: 'screen_group_campaign', withWhereClause: $withWhereClause); + + // ScreenGroupCampaign - screenGroup + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'screenGroup', parentTable: 'screen_group_campaign', childTable: 'screen_group', withWhereClause: $withWhereClause); + + // PlaylistScreenRegion + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'playlist', parentTable: 'playlist_screen_region', childTable: 'playlist', withWhereClause: $withWhereClause); + + // ScreenLayoutRegions + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'regions', parentTable: 'screen_layout_regions', childTable: 'playlist_screen_region', parentTableId: 'id', childTableId: 'region_id', withWhereClause: $withWhereClause); + + // ScreenLayout + $sqlQueries[] = $this->getOneToManyQuery(jsonKey: 'regions', parentTable: 'screen_layout', childTable: 'screen_layout_regions', withWhereClause: $withWhereClause); + + // Screen + $sqlQueries[] = $this->getOneToManyQuery(jsonKey: 'campaigns', parentTable: 'screen', childTable: 'screen_campaign', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getToOneQuery(jsonKey: 'layout', parentTable: 'screen', childTable: 'screen_layout', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getOneToManyQuery(jsonKey: 'regions', parentTable: 'screen', childTable: 'playlist_screen_region', withWhereClause: $withWhereClause); + $sqlQueries[] = $this->getManyToManyQuery(jsonKey: 'inScreenGroups', parentTable: 'screen', pivotTable: 'screen_group_screen', childTable: 'screen_group', withWhereClause: $withWhereClause); + + // Add reset 'changed' fields queries + $sqlQueries = array_merge($sqlQueries, $this->getResetChangedQueries()); + + return $sqlQueries; + } + + /** + * Get "One/ManyToOne" query. + * + * For a table (parent) that has a relation to another table (child) where we need to update the "relations_checksum" + * field on the parent with a checksum of values from the child we need to join the tables and set the values. + * + * Basically we do: "Update parent, join child, set parent value = SHA(child values)" + * + * Example: + * UPDATE slide p + * INNER JOIN theme c ON p.theme_id = c.id + * SET p.changed = 1, + * p.relations_checksum = JSON_SET(p.relations_checksum, "$.theme", SHA1(CONCAT(c.id, c.version, c.relations_checksum))) + * WHERE + * p.changed = 1 + * OR c.changed = 1 + * + * @param string|null $parentTableId + */ + private function getToOneQuery(string $jsonKey, string $parentTable, string $childTable, ?string $parentTableId = null, string $childTableId = 'id', bool $withWhereClause = true): string + { + // Set the column name to use for "ON" in the Join clause. By default, the child table name with "_id" appended. + // E.g. "UPDATE feed p INNER JOIN feed_source c ON p.feed_source_id = c.id" + $parentTableId ??= $childTable.'_id'; + + // The base UPDATE query. + // - Use INNER JON to only select rows that have a match in both parent and child tables + // - Use JSON_SET to only INSERT/UPDATE the relevant key in the json object, not the whole field. + $queryFormat = ' + UPDATE %s p + INNER JOIN %s c ON p.%s = c.%s + SET p.changed = 1, + p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", SHA1(CONCAT(c.id, c.version, c.relations_checksum))) + '; + + $query = sprintf($queryFormat, $parentTable, $childTable, $parentTableId, $childTableId, $jsonKey); + + // Add WHERE clause to only update rows that have been modified since ":modified_at" + if ($withWhereClause) { + $query .= ' WHERE p.changed = 1 OR c.changed = 1'; + } + + return $query; + } + + /** + * Get "OnetoMany" query. + * + * For a table (parent) that has a toMany relationship to another table (child) where we need to update the "relations_checksum" + * field on the parent with a checksum of values from the child we need to join the tables and set the values. + * + * Example: + * UPDATE + * playlist p + * INNER JOIN ( + * SELECT + * c.playlist_id, + * CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, + * SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum + * FROM + * playlist_slide c + * GROUP BY + * c.playlist_id + * ) temp ON p.id = temp.playlist_id + * SET p.changed = 1, + * p.relations_checksum = JSON_SET(p.relations_checksum, "$.slides", temp.checksum) + * WHERE p.changed = 1 OR temp.changed = 1 + */ + private function getOneToManyQuery(string $jsonKey, string $parentTable, string $childTable, bool $withWhereClause = true): string + { + $parentTableId = $parentTable.'_id'; + + $queryFormat = ' + UPDATE + %s p + INNER JOIN ( + SELECT + c.%s, + CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, + SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum + FROM + %s c + GROUP BY + c.%s + ) temp ON p.id = temp.%s + SET p.changed = 1, + p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", temp.checksum) + '; + + $query = sprintf($queryFormat, $parentTable, $parentTableId, $childTable, $parentTableId, $parentTableId, $jsonKey); + + if ($withWhereClause) { + $query .= ' WHERE p.changed = 1 OR temp.changed = 1'; + } + + return $query; + } + + /** + * Get "many to many" query. + * + * For a table (parent) that has a relation to another table (child) through a pivot table where we need to update the "changed" + * and "relations_checksum" fields on the parent with values from the child we need to join the tables and set the values. + * + * Example: + * UPDATE + * slide p + * INNER JOIN ( + * SELECT + * pivot.slide_id, + * CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, + * SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum + * FROM + * slide_media pivot + * INNER JOIN media c ON pivot.media_id = c.id + * GROUP BY + * pivot.slide_id + * ) temp ON p.id = temp.slide_id + * SET p.changed = 1, + * p.relations_checksum = JSON_SET(p.relations_checksum, "$.media", temp.checksum) + * WHERE p.changed = 1 OR temp.changed = 1 + */ + private function getManyToManyQuery(string $jsonKey, string $parentTable, string $pivotTable, string $childTable, bool $withWhereClause = true): string + { + $parentTableId = $parentTable.'_id'; + $childTableId = $childTable.'_id'; + + $queryFormat = ' + UPDATE + %s p + INNER JOIN ( + SELECT + pivot.%s, + CAST(GROUP_CONCAT(DISTINCT c.changed SEPARATOR "") > 0 AS UNSIGNED) changed, + SHA1(GROUP_CONCAT(c.id, c.version, c.relations_checksum)) checksum + FROM + %s pivot + INNER JOIN %s c ON pivot.%s = c.id + GROUP BY + pivot.%s + ) temp ON p.id = temp.%s + SET p.changed = 1, + p.relations_checksum = JSON_SET(p.relations_checksum, "$.%s", temp.checksum) + '; + + $query = sprintf($queryFormat, $parentTable, $parentTableId, $pivotTable, $childTable, $childTableId, $parentTableId, $parentTableId, $jsonKey); + if ($withWhereClause) { + $query .= ' WHERE p.changed = 1 OR temp.changed = 1'; + } + + return $query; + } + + /** + * Get an array of queries to reset all "changed" fields to 0. + * + * @return string[] + */ + private function getResetChangedQueries(): array + { + $queries = []; + foreach (self::CHECKSUM_TABLES as $table) { + $queries[] = sprintf('UPDATE %s SET changed = 0 WHERE changed = 1', $table); + } + + return $queries; + } +} From d85399f74ef4a451f576b75cd4ec997d2d365d22 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 27 Feb 2026 09:12:02 +0100 Subject: [PATCH 41/47] Fix Psalm errors in RecalculateChecksumCommand Add #[\Override] attributes to configure(), complete(), and execute(). Add explicit Doctrine types to setParameter() calls for tenant and date. Co-Authored-By: Claude Opus 4.6 --- src/Command/Checksum/RecalculateChecksumCommand.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Command/Checksum/RecalculateChecksumCommand.php b/src/Command/Checksum/RecalculateChecksumCommand.php index f1d1f789b..43d5b53a9 100644 --- a/src/Command/Checksum/RecalculateChecksumCommand.php +++ b/src/Command/Checksum/RecalculateChecksumCommand.php @@ -4,6 +4,7 @@ namespace App\Command\Checksum; +use App\Entity\Tenant; use App\Entity\Tenant\Media; use App\Entity\Tenant\Slide; use App\Repository\TenantRepository; @@ -36,6 +37,7 @@ public function __construct( parent::__construct(); } + #[\Override] protected function configure(): void { $this @@ -58,6 +60,7 @@ protected function configure(): void ; } + #[\Override] public function complete(CompletionInput $input, CompletionSuggestions $suggestions): void { if ($input->mustSuggestOptionValuesFor(self::OPTION_TENANT)) { @@ -68,6 +71,7 @@ public function complete(CompletionInput $input, CompletionSuggestions $suggesti } } + #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $io = new SymfonyStyle($input, $output); @@ -117,12 +121,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int if (null !== $tenant) { $qb->andWhere('e.tenant = :tenant') - ->setParameter('tenant', $tenant); + ->setParameter('tenant', $tenant, Tenant::class); } if (null !== $modifiedAfter) { $qb->andWhere('e.modifiedAt >= :modifiedAfter') - ->setParameter('modifiedAfter', $modifiedAfter); + ->setParameter('modifiedAfter', $modifiedAfter, 'datetime_immutable'); } $affected = $qb->getQuery()->execute(); From 204f866f292b9bbb52923a268a24f345394b8cdb Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 2 Mar 2026 10:58:08 +0100 Subject: [PATCH 42/47] 6592: Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e92347c..d050fe078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - [#347](https://github.com/os2display/display-api-service/pull/347) - Added onFlush listener to handle ManyToMany collection changes for relations checksum propagation. + - Added command to refresh relation checksums. ## [2.6.0] - 2025-12-05 From fbdf31aae27d1c9c2ec5621e4c5d80705f653c6e Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:22:07 +0100 Subject: [PATCH 43/47] 6592: Composer update --- composer.lock | 739 +++++++++++++++++++++++++------------------------- 1 file changed, 370 insertions(+), 369 deletions(-) diff --git a/composer.lock b/composer.lock index d6fd19db3..846da321c 100644 --- a/composer.lock +++ b/composer.lock @@ -755,16 +755,16 @@ }, { "name": "doctrine/collections", - "version": "2.4.0", + "version": "2.6.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "9acfeea2e8666536edff3d77c531261c63680160" + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160", - "reference": "9acfeea2e8666536edff3d77c531261c63680160", + "url": "https://api.github.com/repos/doctrine/collections/zipball/7713da39d8e237f28411d6a616a3dce5e20d5de2", + "reference": "7713da39d8e237f28411d6a616a3dce5e20d5de2", "shasum": "" }, "require": { @@ -821,7 +821,7 @@ ], "support": { "issues": "https://github.com/doctrine/collections/issues", - "source": "https://github.com/doctrine/collections/tree/2.4.0" + "source": "https://github.com/doctrine/collections/tree/2.6.0" }, "funding": [ { @@ -837,7 +837,7 @@ "type": "tidelift" } ], - "time": "2025-10-25T09:18:13+00:00" + "time": "2026-01-15T10:01:58+00:00" }, { "name": "doctrine/common", @@ -932,16 +932,16 @@ }, { "name": "doctrine/dbal", - "version": "3.10.4", + "version": "3.10.5", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "63a46cb5aa6f60991186cc98c1d1b50c09311868" + "reference": "95d84866bf3c04b2ddca1df7c049714660959aef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/63a46cb5aa6f60991186cc98c1d1b50c09311868", - "reference": "63a46cb5aa6f60991186cc98c1d1b50c09311868", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/95d84866bf3c04b2ddca1df7c049714660959aef", + "reference": "95d84866bf3c04b2ddca1df7c049714660959aef", "shasum": "" }, "require": { @@ -962,9 +962,9 @@ "jetbrains/phpstorm-stubs": "2023.1", "phpstan/phpstan": "2.1.30", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "9.6.29", - "slevomat/coding-standard": "8.24.0", - "squizlabs/php_codesniffer": "4.0.0", + "phpunit/phpunit": "9.6.34", + "slevomat/coding-standard": "8.27.1", + "squizlabs/php_codesniffer": "4.0.1", "symfony/cache": "^5.4|^6.0|^7.0|^8.0", "symfony/console": "^4.4|^5.4|^6.0|^7.0|^8.0" }, @@ -1026,7 +1026,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.10.4" + "source": "https://github.com/doctrine/dbal/tree/3.10.5" }, "funding": [ { @@ -1042,33 +1042,33 @@ "type": "tidelift" } ], - "time": "2025-11-29T10:46:08+00:00" + "time": "2026-02-24T08:03:57+00:00" }, { "name": "doctrine/deprecations", - "version": "1.1.5", + "version": "1.1.6", "source": { "type": "git", "url": "https://github.com/doctrine/deprecations.git", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38" + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", - "reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", + "reference": "d4fe3e6fd9bb9e72557a19674f44d8ac7db4c6ca", "shasum": "" }, "require": { "php": "^7.1 || ^8.0" }, "conflict": { - "phpunit/phpunit": "<=7.5 || >=13" + "phpunit/phpunit": "<=7.5 || >=14" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^12 || ^13", - "phpstan/phpstan": "1.4.10 || 2.1.11", + "doctrine/coding-standard": "^9 || ^12 || ^14", + "phpstan/phpstan": "1.4.10 || 2.1.30", "phpstan/phpstan-phpunit": "^1.0 || ^2", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12.4 || ^13.0", "psr/log": "^1 || ^2 || ^3" }, "suggest": { @@ -1088,9 +1088,9 @@ "homepage": "https://www.doctrine-project.org/", "support": { "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.5" + "source": "https://github.com/doctrine/deprecations/tree/1.1.6" }, - "time": "2025-04-07T20:06:18+00:00" + "time": "2026-02-07T07:09:04+00:00" }, { "name": "doctrine/doctrine-bundle", @@ -1300,16 +1300,16 @@ }, { "name": "doctrine/event-manager", - "version": "2.0.1", + "version": "2.1.1", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e" + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/b680156fa328f1dfd874fd48c7026c41570b9c6e", - "reference": "b680156fa328f1dfd874fd48c7026c41570b9c6e", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/dda33921b198841ca8dbad2eaa5d4d34769d18cf", + "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf", "shasum": "" }, "require": { @@ -1319,10 +1319,10 @@ "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^12", - "phpstan/phpstan": "^1.8.8", - "phpunit/phpunit": "^10.5", - "vimeo/psalm": "^5.24" + "doctrine/coding-standard": "^14", + "phpdocumentor/guides-cli": "^1.4", + "phpstan/phpstan": "^2.1.32", + "phpunit/phpunit": "^10.5.58" }, "type": "library", "autoload": { @@ -1371,7 +1371,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.0.1" + "source": "https://github.com/doctrine/event-manager/tree/2.1.1" }, "funding": [ { @@ -1387,7 +1387,7 @@ "type": "tidelift" } ], - "time": "2024-05-22T20:47:39+00:00" + "time": "2026-01-29T07:11:08+00:00" }, { "name": "doctrine/inflector", @@ -1628,16 +1628,16 @@ }, { "name": "doctrine/migrations", - "version": "3.9.5", + "version": "3.9.6", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "1b823afbc40f932dae8272574faee53f2755eac5" + "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b823afbc40f932dae8272574faee53f2755eac5", - "reference": "1b823afbc40f932dae8272574faee53f2755eac5", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/ffd8355cdd8505fc650d9604f058bf62aedd80a1", + "reference": "ffd8355cdd8505fc650d9604f058bf62aedd80a1", "shasum": "" }, "require": { @@ -1711,7 +1711,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.5" + "source": "https://github.com/doctrine/migrations/tree/3.9.6" }, "funding": [ { @@ -1727,7 +1727,7 @@ "type": "tidelift" } ], - "time": "2025-11-20T11:15:36+00:00" + "time": "2026-02-11T06:46:11+00:00" }, { "name": "doctrine/orm", @@ -1928,16 +1928,16 @@ }, { "name": "doctrine/sql-formatter", - "version": "1.5.3", + "version": "1.5.4", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7" + "reference": "9563949f5cd3bd12a17d12fb980528bc141c5806" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/a8af23a8e9d622505baa2997465782cbe8bb7fc7", - "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7", + "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/9563949f5cd3bd12a17d12fb980528bc141c5806", + "reference": "9563949f5cd3bd12a17d12fb980528bc141c5806", "shasum": "" }, "require": { @@ -1977,9 +1977,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.5.3" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.4" }, - "time": "2025-10-26T09:35:14+00:00" + "time": "2026-02-08T16:21:46+00:00" }, { "name": "evenement/evenement", @@ -2154,16 +2154,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.92.4", + "version": "v3.94.2", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "9e7488b19403423e02e8403cc1eb596baf4673b0" + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9e7488b19403423e02e8403cc1eb596baf4673b0", - "reference": "9e7488b19403423e02e8403cc1eb596baf4673b0", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7787ceff91365ba7d623ec410b8f429cdebb4f63", + "reference": "7787ceff91365ba7d623ec410b8f429cdebb4f63", "shasum": "" }, "require": { @@ -2180,7 +2180,7 @@ "react/event-loop": "^1.5", "react/socket": "^1.16", "react/stream": "^1.4", - "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0", + "sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0 || ^8.0", "symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0", "symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", "symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0", @@ -2194,18 +2194,18 @@ "symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0" }, "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.7", - "infection/infection": "^0.31", - "justinrainbow/json-schema": "^6.6", + "facile-it/paraunit": "^1.3.1 || ^2.7.1", + "infection/infection": "^0.32.3", + "justinrainbow/json-schema": "^6.6.4", "keradus/cli-executor": "^2.3", "mikey179/vfsstream": "^1.6.12", - "php-coveralls/php-coveralls": "^2.9", - "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6", - "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6", - "phpunit/phpunit": "^9.6.31 || ^10.5.60 || ^11.5.46", + "php-coveralls/php-coveralls": "^2.9.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.7", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.7", + "phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.51", "symfony/polyfill-php85": "^1.33", - "symfony/var-dumper": "^5.4.48 || ^6.4.26 || ^7.4.0 || ^8.0", - "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0" + "symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.4", + "symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.1" }, "suggest": { "ext-dom": "For handling output formats in XML", @@ -2246,7 +2246,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.92.4" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.94.2" }, "funding": [ { @@ -2254,7 +2254,7 @@ "type": "github" } ], - "time": "2026-01-04T00:38:52+00:00" + "time": "2026-02-20T16:13:53+00:00" }, { "name": "friendsofphp/proxy-manager-lts", @@ -2745,16 +2745,16 @@ }, { "name": "imagine/imagine", - "version": "1.5.1", + "version": "1.5.2", "source": { "type": "git", "url": "https://github.com/php-imagine/Imagine.git", - "reference": "8b130cd281efdea67e52d5f0f998572eb62d2f04" + "reference": "f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/8b130cd281efdea67e52d5f0f998572eb62d2f04", - "reference": "8b130cd281efdea67e52d5f0f998572eb62d2f04", + "url": "https://api.github.com/repos/php-imagine/Imagine/zipball/f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c", + "reference": "f9ed796eefb77c2f0f2167e1d4e36bc2b5ed6b0c", "shasum": "" }, "require": { @@ -2801,9 +2801,9 @@ ], "support": { "issues": "https://github.com/php-imagine/Imagine/issues", - "source": "https://github.com/php-imagine/Imagine/tree/1.5.1" + "source": "https://github.com/php-imagine/Imagine/tree/1.5.2" }, - "time": "2025-12-09T15:27:47+00:00" + "time": "2026-01-09T10:45:12+00:00" }, { "name": "itk-dev/openid-connect", @@ -2997,16 +2997,16 @@ }, { "name": "justinrainbow/json-schema", - "version": "5.3.1", + "version": "5.3.2", "source": { "type": "git", "url": "https://github.com/jsonrainbow/json-schema.git", - "reference": "b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20" + "reference": "2f7abf648939847a789c55c206d4cb9dd0d53e2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20", - "reference": "b5a44b6391a3bbb75c9f2b73e1ef03d6045e1e20", + "url": "https://api.github.com/repos/jsonrainbow/json-schema/zipball/2f7abf648939847a789c55c206d4cb9dd0d53e2c", + "reference": "2f7abf648939847a789c55c206d4cb9dd0d53e2c", "shasum": "" }, "require": { @@ -3056,22 +3056,22 @@ ], "support": { "issues": "https://github.com/jsonrainbow/json-schema/issues", - "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.1" + "source": "https://github.com/jsonrainbow/json-schema/tree/5.3.2" }, - "time": "2025-12-12T08:56:22+00:00" + "time": "2026-02-27T12:33:19+00:00" }, { "name": "kubawerlos/php-cs-fixer-custom-fixers", - "version": "v3.35.1", + "version": "v3.36.0", "source": { "type": "git", "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", - "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395" + "reference": "e1f97f6463f0b2a22e0dd320948a04132ff9c501" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/2a35f80ae24ca77443a7af1599c3a3db1b6bd395", - "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395", + "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/e1f97f6463f0b2a22e0dd320948a04132ff9c501", + "reference": "e1f97f6463f0b2a22e0dd320948a04132ff9c501", "shasum": "" }, "require": { @@ -3081,7 +3081,7 @@ "php": "^7.4 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.32" + "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.44" }, "type": "library", "autoload": { @@ -3102,7 +3102,7 @@ "description": "A set of custom fixers for PHP CS Fixer", "support": { "issues": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/issues", - "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.35.1" + "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.36.0" }, "funding": [ { @@ -3110,7 +3110,7 @@ "type": "github" } ], - "time": "2025-09-28T18:43:35+00:00" + "time": "2026-01-31T07:02:11+00:00" }, { "name": "laminas/laminas-code", @@ -3498,22 +3498,22 @@ }, { "name": "liip/imagine-bundle", - "version": "2.16.0", + "version": "2.17.1", "source": { "type": "git", "url": "https://github.com/liip/LiipImagineBundle.git", - "reference": "335121ef65d9841af9b40a850aa143cd6b61f847" + "reference": "69d2df3c6606495d1878fa190d6c3dc4bc5623b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/335121ef65d9841af9b40a850aa143cd6b61f847", - "reference": "335121ef65d9841af9b40a850aa143cd6b61f847", + "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/69d2df3c6606495d1878fa190d6c3dc4bc5623b6", + "reference": "69d2df3c6606495d1878fa190d6c3dc4bc5623b6", "shasum": "" }, "require": { "ext-mbstring": "*", "imagine/imagine": "^1.3.2", - "php": "^7.2|^8.0", + "php": "^8.0", "symfony/dependency-injection": "^5.4|^6.4|^7.4|^8.0", "symfony/deprecation-contracts": "^2.5 || ^3", "symfony/filesystem": "^5.4|^6.4|^7.3|^8.0", @@ -3542,6 +3542,7 @@ "symfony/form": "^5.4|^6.4|^7.3|^8.0", "symfony/messenger": "^5.4|^6.4|^7.3|^8.0", "symfony/phpunit-bridge": "^7.3", + "symfony/runtime": "^5.4|^6.4|^7.3|^8.0", "symfony/templating": "^5.4|^6.4|^7.3|^8.0", "symfony/validator": "^5.4|^6.4|^7.3|^8.0", "symfony/yaml": "^5.4|^6.4|^7.3|^8.0" @@ -3599,9 +3600,9 @@ ], "support": { "issues": "https://github.com/liip/LiipImagineBundle/issues", - "source": "https://github.com/liip/LiipImagineBundle/tree/2.16.0" + "source": "https://github.com/liip/LiipImagineBundle/tree/2.17.1" }, - "time": "2025-12-01T10:49:05+00:00" + "time": "2026-01-06T09:34:48+00:00" }, { "name": "masterminds/html5", @@ -3842,16 +3843,16 @@ }, { "name": "nelmio/cors-bundle", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/nelmio/NelmioCorsBundle.git", - "reference": "530217472204881cacd3671909f634b960c7b948" + "reference": "3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/530217472204881cacd3671909f634b960c7b948", - "reference": "530217472204881cacd3671909f634b960c7b948", + "url": "https://api.github.com/repos/nelmio/NelmioCorsBundle/zipball/3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c", + "reference": "3d80dbcd5d1eb5f8b20ed5199e1778d44c2e4d1c", "shasum": "" }, "require": { @@ -3901,9 +3902,9 @@ ], "support": { "issues": "https://github.com/nelmio/NelmioCorsBundle/issues", - "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.6.0" + "source": "https://github.com/nelmio/NelmioCorsBundle/tree/2.6.1" }, - "time": "2025-10-23T06:57:22+00:00" + "time": "2026-01-12T15:59:08+00:00" }, { "name": "nyholm/psr7", @@ -5649,16 +5650,16 @@ }, { "name": "symfony/asset", - "version": "v6.4.24", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab" + "reference": "1bd59aa278691b6310ca56b996cf6e2619a6a347" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/cfee7c0d64be113383db74a2fdd65d426b7f3aab", - "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab", + "url": "https://api.github.com/repos/symfony/asset/zipball/1bd59aa278691b6310ca56b996cf6e2619a6a347", + "reference": "1bd59aa278691b6310ca56b996cf6e2619a6a347", "shasum": "" }, "require": { @@ -5698,7 +5699,7 @@ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/asset/tree/v6.4.24" + "source": "https://github.com/symfony/asset/tree/v6.4.34" }, "funding": [ { @@ -5718,20 +5719,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-02-07T09:15:39+00:00" }, { "name": "symfony/cache", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a1b306757c34b96fe97c0c586f50dceed05c7adb" + "reference": "a0a1690543329685c044362c873b78c6de9d4faa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a1b306757c34b96fe97c0c586f50dceed05c7adb", - "reference": "a1b306757c34b96fe97c0c586f50dceed05c7adb", + "url": "https://api.github.com/repos/symfony/cache/zipball/a0a1690543329685c044362c873b78c6de9d4faa", + "reference": "a0a1690543329685c044362c873b78c6de9d4faa", "shasum": "" }, "require": { @@ -5798,7 +5799,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.31" + "source": "https://github.com/symfony/cache/tree/v6.4.34" }, "funding": [ { @@ -5818,7 +5819,7 @@ "type": "tidelift" } ], - "time": "2025-12-27T18:26:25+00:00" + "time": "2026-02-20T15:06:30+00:00" }, { "name": "symfony/cache-contracts", @@ -5976,16 +5977,16 @@ }, { "name": "symfony/config", - "version": "v6.4.28", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62" + "reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/15947c18ef3ddb0b2f4ec936b9e90e2520979f62", - "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62", + "url": "https://api.github.com/repos/symfony/config/zipball/ce9cb0c0d281aaf188b802d4968e42bfb60701e9", + "reference": "ce9cb0c0d281aaf188b802d4968e42bfb60701e9", "shasum": "" }, "require": { @@ -6031,7 +6032,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.28" + "source": "https://github.com/symfony/config/tree/v6.4.34" }, "funding": [ { @@ -6051,20 +6052,20 @@ "type": "tidelift" } ], - "time": "2025-11-01T19:52:02+00:00" + "time": "2026-02-24T17:34:50+00:00" }, { "name": "symfony/console", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997" + "reference": "7b1f1c37eff5910ddda2831345467e593a5120ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f9f8a889f54c264f9abac3fc0f7a371ffca51997", - "reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997", + "url": "https://api.github.com/repos/symfony/console/zipball/7b1f1c37eff5910ddda2831345467e593a5120ad", + "reference": "7b1f1c37eff5910ddda2831345467e593a5120ad", "shasum": "" }, "require": { @@ -6129,7 +6130,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.31" + "source": "https://github.com/symfony/console/tree/v6.4.34" }, "funding": [ { @@ -6149,20 +6150,20 @@ "type": "tidelift" } ], - "time": "2025-12-22T08:30:34+00:00" + "time": "2026-02-23T15:42:15+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "10058832a74a33648870aa2057e3fdc8796a6566" + "reference": "91e49958b8a6092e48e4711894a1aeb1b151c62a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/10058832a74a33648870aa2057e3fdc8796a6566", - "reference": "10058832a74a33648870aa2057e3fdc8796a6566", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/91e49958b8a6092e48e4711894a1aeb1b151c62a", + "reference": "91e49958b8a6092e48e4711894a1aeb1b151c62a", "shasum": "" }, "require": { @@ -6214,7 +6215,7 @@ "description": "Allows you to standardize and centralize the way objects are constructed in your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dependency-injection/tree/v6.4.31" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.34" }, "funding": [ { @@ -6234,7 +6235,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T13:34:50+00:00" + "time": "2026-02-24T15:33:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6305,16 +6306,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.26", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344" + "reference": "9e82991eda36e85b640644e1d8d34d89eff498a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/c14bb5a9125c411e73354954940e06b6e7fcc344", - "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/9e82991eda36e85b640644e1d8d34d89eff498a6", + "reference": "9e82991eda36e85b640644e1d8d34d89eff498a6", "shasum": "" }, "require": { @@ -6393,7 +6394,7 @@ "description": "Provides integration for Doctrine with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.26" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.34" }, "funding": [ { @@ -6413,20 +6414,20 @@ "type": "tidelift" } ], - "time": "2025-09-26T15:07:38+00:00" + "time": "2026-02-06T08:53:22+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.4.25", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524" + "reference": "ec0d22e1b89d5767a44f7abb63a1f1439bd9c735" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/976302990f9f2a6d4c07206836dd4ca77cae9524", - "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ec0d22e1b89d5767a44f7abb63a1f1439bd9c735", + "reference": "ec0d22e1b89d5767a44f7abb63a1f1439bd9c735", "shasum": "" }, "require": { @@ -6464,7 +6465,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v6.4.25" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.34" }, "funding": [ { @@ -6484,7 +6485,7 @@ "type": "tidelift" } ], - "time": "2025-08-05T18:56:08+00:00" + "time": "2026-02-16T20:44:03+00:00" }, { "name": "symfony/dotenv", @@ -6566,16 +6567,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.4.26", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c" + "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/41bedcaec5b72640b0ec2096547b75fda72ead6c", - "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/8c18400784fcb014dc73c8d5601a9576af7f8ad4", + "reference": "8c18400784fcb014dc73c8d5601a9576af7f8ad4", "shasum": "" }, "require": { @@ -6621,7 +6622,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.4.26" + "source": "https://github.com/symfony/error-handler/tree/v6.4.32" }, "funding": [ { @@ -6641,20 +6642,20 @@ "type": "tidelift" } ], - "time": "2025-09-11T09:57:09+00:00" + "time": "2026-01-19T19:28:19+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.25", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "b0cf3162020603587363f0551cd3be43958611ff" + "reference": "99d7e101826e6610606b9433248f80c1997cd20b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b0cf3162020603587363f0551cd3be43958611ff", - "reference": "b0cf3162020603587363f0551cd3be43958611ff", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/99d7e101826e6610606b9433248f80c1997cd20b", + "reference": "99d7e101826e6610606b9433248f80c1997cd20b", "shasum": "" }, "require": { @@ -6705,7 +6706,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.25" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.32" }, "funding": [ { @@ -6725,7 +6726,7 @@ "type": "tidelift" } ], - "time": "2025-08-13T09:41:44+00:00" + "time": "2026-01-05T11:13:48+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6805,16 +6806,16 @@ }, { "name": "symfony/expression-language", - "version": "v6.4.30", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "01906f3b379833b347de9abc8ddc326593e9122b" + "reference": "89c10ef5ca65968ec7ce7ce033c7f36eeb1b0312" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/01906f3b379833b347de9abc8ddc326593e9122b", - "reference": "01906f3b379833b347de9abc8ddc326593e9122b", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/89c10ef5ca65968ec7ce7ce033c7f36eeb1b0312", + "reference": "89c10ef5ca65968ec7ce7ce033c7f36eeb1b0312", "shasum": "" }, "require": { @@ -6849,7 +6850,7 @@ "description": "Provides an engine that can compile and evaluate expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/expression-language/tree/v6.4.30" + "source": "https://github.com/symfony/expression-language/tree/v6.4.32" }, "funding": [ { @@ -6869,20 +6870,20 @@ "type": "tidelift" } ], - "time": "2025-11-09T10:02:06+00:00" + "time": "2026-01-04T11:52:13+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789" + "reference": "01ffe0411b842f93c571e5c391f289c3fdd498c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/441c6b69f7222aadae7cbf5df588496d5ee37789", - "reference": "441c6b69f7222aadae7cbf5df588496d5ee37789", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/01ffe0411b842f93c571e5c391f289c3fdd498c3", + "reference": "01ffe0411b842f93c571e5c391f289c3fdd498c3", "shasum": "" }, "require": { @@ -6919,7 +6920,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.30" + "source": "https://github.com/symfony/filesystem/tree/v6.4.34" }, "funding": [ { @@ -6939,20 +6940,20 @@ "type": "tidelift" } ], - "time": "2025-11-26T14:43:45+00:00" + "time": "2026-02-24T17:51:06+00:00" }, { "name": "symfony/finder", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b" + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/5547f2e1f0ca8e2e7abe490156b62da778cfbe2b", - "reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b", + "url": "https://api.github.com/repos/symfony/finder/zipball/9590e86be1d1c57bfbb16d0dd040345378c20896", + "reference": "9590e86be1d1c57bfbb16d0dd040345378c20896", "shasum": "" }, "require": { @@ -6987,7 +6988,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.31" + "source": "https://github.com/symfony/finder/tree/v6.4.34" }, "funding": [ { @@ -7007,7 +7008,7 @@ "type": "tidelift" } ], - "time": "2025-12-11T14:52:17+00:00" + "time": "2026-01-28T15:16:37+00:00" }, { "name": "symfony/flex", @@ -7084,16 +7085,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "0ab60c05570b9e2bfab92b9944b938b8ffb5ba96" + "reference": "5b5d19473f22d699811a41b01cef2462bc42b238" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/0ab60c05570b9e2bfab92b9944b938b8ffb5ba96", - "reference": "0ab60c05570b9e2bfab92b9944b938b8ffb5ba96", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/5b5d19473f22d699811a41b01cef2462bc42b238", + "reference": "5b5d19473f22d699811a41b01cef2462bc42b238", "shasum": "" }, "require": { @@ -7213,7 +7214,7 @@ "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/framework-bundle/tree/v6.4.31" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.34" }, "funding": [ { @@ -7233,20 +7234,20 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:16:13+00:00" + "time": "2026-02-24T16:00:52+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "f166fe476c996237666bcf7ec2cf827cd82ad573" + "reference": "0dc71f52e5d35bb045fd0f82b1a80c027971d551" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/f166fe476c996237666bcf7ec2cf827cd82ad573", - "reference": "f166fe476c996237666bcf7ec2cf827cd82ad573", + "url": "https://api.github.com/repos/symfony/http-client/zipball/0dc71f52e5d35bb045fd0f82b1a80c027971d551", + "reference": "0dc71f52e5d35bb045fd0f82b1a80c027971d551", "shasum": "" }, "require": { @@ -7311,7 +7312,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.31" + "source": "https://github.com/symfony/http-client/tree/v6.4.34" }, "funding": [ { @@ -7331,7 +7332,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:19:38+00:00" + "time": "2026-02-18T07:27:25+00:00" }, { "name": "symfony/http-client-contracts", @@ -7413,16 +7414,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a35ee6f47e4775179704d7877a8b0da3cb09241a" + "reference": "5bb346d1b4b2a616e5c3d99b3ee4d5810735c535" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a35ee6f47e4775179704d7877a8b0da3cb09241a", - "reference": "a35ee6f47e4775179704d7877a8b0da3cb09241a", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/5bb346d1b4b2a616e5c3d99b3ee4d5810735c535", + "reference": "5bb346d1b4b2a616e5c3d99b3ee4d5810735c535", "shasum": "" }, "require": { @@ -7470,7 +7471,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.4.31" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.34" }, "funding": [ { @@ -7490,20 +7491,20 @@ "type": "tidelift" } ], - "time": "2025-12-17T10:10:57+00:00" + "time": "2026-02-21T15:48:41+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "16b0d46d8e11f480345c15b229cfc827a8a0f731" + "reference": "006a49fc4f41ee21a6ca61e69caed1c30b29f07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/16b0d46d8e11f480345c15b229cfc827a8a0f731", - "reference": "16b0d46d8e11f480345c15b229cfc827a8a0f731", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/006a49fc4f41ee21a6ca61e69caed1c30b29f07c", + "reference": "006a49fc4f41ee21a6ca61e69caed1c30b29f07c", "shasum": "" }, "require": { @@ -7544,7 +7545,7 @@ "symfony/config": "^6.1|^7.0", "symfony/console": "^5.4|^6.0|^7.0", "symfony/css-selector": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4.1|^7.0.1", "symfony/dom-crawler": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", @@ -7588,7 +7589,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.4.31" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.34" }, "funding": [ { @@ -7608,20 +7609,20 @@ "type": "tidelift" } ], - "time": "2025-12-31T08:27:27+00:00" + "time": "2026-02-26T08:27:11+00:00" }, { "name": "symfony/mime", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "69aeef5d2692bb7c18ce133b09f67b27260b7acf" + "reference": "2b32fbbe10b36a8379efab6e702ad8b917151839" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/69aeef5d2692bb7c18ce133b09f67b27260b7acf", - "reference": "69aeef5d2692bb7c18ce133b09f67b27260b7acf", + "url": "https://api.github.com/repos/symfony/mime/zipball/2b32fbbe10b36a8379efab6e702ad8b917151839", + "reference": "2b32fbbe10b36a8379efab6e702ad8b917151839", "shasum": "" }, "require": { @@ -7677,7 +7678,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.30" + "source": "https://github.com/symfony/mime/tree/v6.4.34" }, "funding": [ { @@ -7697,20 +7698,20 @@ "type": "tidelift" } ], - "time": "2025-11-16T09:57:53+00:00" + "time": "2026-02-02T17:01:23+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v6.4.28", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b" + "reference": "ee2d0150031b7c6ee2a1149fddddef3e7cdec117" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/d2f4b68e3247cf44d93f48545c8c072a75c17e5b", - "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/ee2d0150031b7c6ee2a1149fddddef3e7cdec117", + "reference": "ee2d0150031b7c6ee2a1149fddddef3e7cdec117", "shasum": "" }, "require": { @@ -7760,7 +7761,7 @@ "description": "Provides integration for Monolog with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.28" + "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.34" }, "funding": [ { @@ -7780,7 +7781,7 @@ "type": "tidelift" } ], - "time": "2025-10-30T19:57:08+00:00" + "time": "2026-02-16T20:44:03+00:00" }, { "name": "symfony/monolog-bundle", @@ -7935,16 +7936,16 @@ }, { "name": "symfony/password-hasher", - "version": "v6.4.24", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557" + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/dcab5ac87450aaed26483ba49c2ce86808da7557", - "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/fbdfa5a2ca218ec8bb9029517426df2d780bdba9", + "reference": "fbdfa5a2ca218ec8bb9029517426df2d780bdba9", "shasum": "" }, "require": { @@ -7987,7 +7988,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.24" + "source": "https://github.com/symfony/password-hasher/tree/v6.4.32" }, "funding": [ { @@ -8007,7 +8008,7 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-01-01T21:24:53+00:00" }, { "name": "symfony/polyfill-intl-grapheme", @@ -8825,16 +8826,16 @@ }, { "name": "symfony/process", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "8541b7308fca001320e90bca8a73a28aa5604a6e" + "reference": "c46e854e79b52d07666e43924a20cb6dc546644e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/8541b7308fca001320e90bca8a73a28aa5604a6e", - "reference": "8541b7308fca001320e90bca8a73a28aa5604a6e", + "url": "https://api.github.com/repos/symfony/process/zipball/c46e854e79b52d07666e43924a20cb6dc546644e", + "reference": "c46e854e79b52d07666e43924a20cb6dc546644e", "shasum": "" }, "require": { @@ -8866,7 +8867,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.31" + "source": "https://github.com/symfony/process/tree/v6.4.33" }, "funding": [ { @@ -8886,26 +8887,26 @@ "type": "tidelift" } ], - "time": "2025-12-15T19:26:35+00:00" + "time": "2026-01-23T16:02:12+00:00" }, { "name": "symfony/property-access", - "version": "v6.4.31", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "1b1044599d7fb93cdb82f5a1291ba66f1caf6119" + "reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/1b1044599d7fb93cdb82f5a1291ba66f1caf6119", - "reference": "1b1044599d7fb93cdb82f5a1291ba66f1caf6119", + "url": "https://api.github.com/repos/symfony/property-access/zipball/6dfa655ac9e9860c05cabb287f34da86b18c237e", + "reference": "6dfa655ac9e9860c05cabb287f34da86b18c237e", "shasum": "" }, "require": { "php": ">=8.1", "symfony/deprecation-contracts": "^2.5|^3", - "symfony/property-info": "^6.4.31|~7.3.9|^7.4.2" + "symfony/property-info": "^6.4.32|~7.3.10|^7.4.4" }, "require-dev": { "symfony/cache": "^5.4|^6.0|^7.0" @@ -8947,7 +8948,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.4.31" + "source": "https://github.com/symfony/property-access/tree/v6.4.32" }, "funding": [ { @@ -8967,20 +8968,20 @@ "type": "tidelift" } ], - "time": "2025-12-18T08:11:26+00:00" + "time": "2026-01-05T08:25:17+00:00" }, { "name": "symfony/property-info", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "f155cef234af1c16ed47791d182e146df237b35f" + "reference": "916455e4c9dcddbebfd101f29d7983841c3564e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/f155cef234af1c16ed47791d182e146df237b35f", - "reference": "f155cef234af1c16ed47791d182e146df237b35f", + "url": "https://api.github.com/repos/symfony/property-info/zipball/916455e4c9dcddbebfd101f29d7983841c3564e0", + "reference": "916455e4c9dcddbebfd101f29d7983841c3564e0", "shasum": "" }, "require": { @@ -8989,7 +8990,7 @@ }, "conflict": { "doctrine/annotations": "<1.12", - "phpdocumentor/reflection-docblock": "<5.2", + "phpdocumentor/reflection-docblock": "<5.2|>=6", "phpdocumentor/type-resolver": "<1.5.1", "symfony/cache": "<5.4", "symfony/dependency-injection": "<5.4|>=6.0,<6.4", @@ -9037,7 +9038,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.31" + "source": "https://github.com/symfony/property-info/tree/v6.4.34" }, "funding": [ { @@ -9057,7 +9058,7 @@ "type": "tidelift" } ], - "time": "2025-12-16T19:55:30+00:00" + "time": "2026-02-13T09:42:46+00:00" }, { "name": "symfony/proxy-manager-bridge", @@ -9132,16 +9133,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ea50a13c2711eebcbb66b38ef6382e62e3262859" + "reference": "5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ea50a13c2711eebcbb66b38ef6382e62e3262859", - "reference": "ea50a13c2711eebcbb66b38ef6382e62e3262859", + "url": "https://api.github.com/repos/symfony/routing/zipball/5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47", + "reference": "5ab3a3e1a03535ec5ca6ce2d39e4369a1096ae47", "shasum": "" }, "require": { @@ -9195,7 +9196,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.30" + "source": "https://github.com/symfony/routing/tree/v6.4.34" }, "funding": [ { @@ -9215,7 +9216,7 @@ "type": "tidelift" } ], - "time": "2025-11-22T09:51:35+00:00" + "time": "2026-02-24T17:34:50+00:00" }, { "name": "symfony/runtime", @@ -9302,16 +9303,16 @@ }, { "name": "symfony/security-bundle", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "508e67e68156cf3cb2b982504191b2ce34daa921" + "reference": "f67bd24782a80095e9b8953e18d01983b9fe8e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/508e67e68156cf3cb2b982504191b2ce34daa921", - "reference": "508e67e68156cf3cb2b982504191b2ce34daa921", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/f67bd24782a80095e9b8953e18d01983b9fe8e34", + "reference": "f67bd24782a80095e9b8953e18d01983b9fe8e34", "shasum": "" }, "require": { @@ -9394,7 +9395,7 @@ "description": "Provides a tight integration of the Security component into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-bundle/tree/v6.4.30" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.34" }, "funding": [ { @@ -9414,7 +9415,7 @@ "type": "tidelift" } ], - "time": "2025-12-04T18:05:02+00:00" + "time": "2026-02-22T21:48:58+00:00" }, { "name": "symfony/security-core", @@ -9580,16 +9581,16 @@ }, { "name": "symfony/security-http", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "2f4ddc4a79b0e6f7dcc72e5ebd7109b3436b967a" + "reference": "894bb42b39bfb240a1f82c9a46a1ce9402a31a6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/2f4ddc4a79b0e6f7dcc72e5ebd7109b3436b967a", - "reference": "2f4ddc4a79b0e6f7dcc72e5ebd7109b3436b967a", + "url": "https://api.github.com/repos/symfony/security-http/zipball/894bb42b39bfb240a1f82c9a46a1ce9402a31a6f", + "reference": "894bb42b39bfb240a1f82c9a46a1ce9402a31a6f", "shasum": "" }, "require": { @@ -9648,7 +9649,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.31" + "source": "https://github.com/symfony/security-http/tree/v6.4.34" }, "funding": [ { @@ -9668,20 +9669,20 @@ "type": "tidelift" } ], - "time": "2025-12-17T22:32:13+00:00" + "time": "2026-02-16T20:44:03+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "abf80f880943224afca831d7da6eff584c3af751" + "reference": "26446be5ec3d84c2aa16a08e195c783e3d4c2af7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/abf80f880943224afca831d7da6eff584c3af751", - "reference": "abf80f880943224afca831d7da6eff584c3af751", + "url": "https://api.github.com/repos/symfony/serializer/zipball/26446be5ec3d84c2aa16a08e195c783e3d4c2af7", + "reference": "26446be5ec3d84c2aa16a08e195c783e3d4c2af7", "shasum": "" }, "require": { @@ -9750,7 +9751,7 @@ "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/serializer/tree/v6.4.31" + "source": "https://github.com/symfony/serializer/tree/v6.4.34" }, "funding": [ { @@ -9770,7 +9771,7 @@ "type": "tidelift" } ], - "time": "2025-12-19T17:17:42+00:00" + "time": "2026-02-24T16:55:33+00:00" }, { "name": "symfony/service-contracts", @@ -9927,16 +9928,16 @@ }, { "name": "symfony/string", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb" + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/50590a057841fa6bf69d12eceffce3465b9e32cb", - "reference": "50590a057841fa6bf69d12eceffce3465b9e32cb", + "url": "https://api.github.com/repos/symfony/string/zipball/2adaf4106f2ef4c67271971bde6d3fe0a6936432", + "reference": "2adaf4106f2ef4c67271971bde6d3fe0a6936432", "shasum": "" }, "require": { @@ -9992,7 +9993,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.30" + "source": "https://github.com/symfony/string/tree/v6.4.34" }, "funding": [ { @@ -10012,7 +10013,7 @@ "type": "tidelift" } ], - "time": "2025-11-21T18:03:05+00:00" + "time": "2026-02-08T20:44:54+00:00" }, { "name": "symfony/translation-contracts", @@ -10098,16 +10099,16 @@ }, { "name": "symfony/twig-bridge", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "24a498d80fd2a28087fbac0a96e0721ce2756b65" + "reference": "5169074f4a88dfb02eeccddaba78edfdf212a9b2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/24a498d80fd2a28087fbac0a96e0721ce2756b65", - "reference": "24a498d80fd2a28087fbac0a96e0721ce2756b65", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/5169074f4a88dfb02eeccddaba78edfdf212a9b2", + "reference": "5169074f4a88dfb02eeccddaba78edfdf212a9b2", "shasum": "" }, "require": { @@ -10120,7 +10121,7 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/console": "<5.4", - "symfony/form": "<6.4", + "symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4", "symfony/http-foundation": "<5.4", "symfony/http-kernel": "<6.4", "symfony/mime": "<6.2", @@ -10138,7 +10139,7 @@ "symfony/dependency-injection": "^5.4|^6.0|^7.0", "symfony/expression-language": "^5.4|^6.0|^7.0", "symfony/finder": "^5.4|^6.0|^7.0", - "symfony/form": "^6.4.30|~7.3.8|^7.4.1", + "symfony/form": "^6.4.32|~7.3.10|^7.4.4", "symfony/html-sanitizer": "^6.1|^7.0", "symfony/http-foundation": "^5.4|^6.0|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -10187,7 +10188,7 @@ "description": "Provides integration for Twig with various Symfony components", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bridge/tree/v6.4.31" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.34" }, "funding": [ { @@ -10207,20 +10208,20 @@ "type": "tidelift" } ], - "time": "2025-12-11T18:16:47+00:00" + "time": "2026-02-23T18:17:33+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.4.31", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "df14e1b81483b04534317e8f61617560ab60777d" + "reference": "a5c8dcc11a5bf9c96320da20070d2e158a4e0b30" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/df14e1b81483b04534317e8f61617560ab60777d", - "reference": "df14e1b81483b04534317e8f61617560ab60777d", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/a5c8dcc11a5bf9c96320da20070d2e158a4e0b30", + "reference": "a5c8dcc11a5bf9c96320da20070d2e158a4e0b30", "shasum": "" }, "require": { @@ -10275,7 +10276,7 @@ "description": "Provides a tight integration of Twig into the Symfony full-stack framework", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/twig-bundle/tree/v6.4.31" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.32" }, "funding": [ { @@ -10295,20 +10296,20 @@ "type": "tidelift" } ], - "time": "2025-12-18T03:19:37+00:00" + "time": "2026-01-05T12:44:39+00:00" }, { "name": "symfony/uid", - "version": "v6.4.24", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "17da16a750541a42cf2183935e0f6008316c23f7" + "reference": "6b973c385f00341b246f697d82dc01a09107acdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/17da16a750541a42cf2183935e0f6008316c23f7", - "reference": "17da16a750541a42cf2183935e0f6008316c23f7", + "url": "https://api.github.com/repos/symfony/uid/zipball/6b973c385f00341b246f697d82dc01a09107acdd", + "reference": "6b973c385f00341b246f697d82dc01a09107acdd", "shasum": "" }, "require": { @@ -10353,7 +10354,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.24" + "source": "https://github.com/symfony/uid/tree/v6.4.32" }, "funding": [ { @@ -10373,20 +10374,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2025-12-23T15:07:59+00:00" }, { "name": "symfony/validator", - "version": "v6.4.31", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "0c3f60adce4e6fc86583b0c7e363ce90fe3ca3e7" + "reference": "7c3897b7f739d4ab913481e680405ca82d08084d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/0c3f60adce4e6fc86583b0c7e363ce90fe3ca3e7", - "reference": "0c3f60adce4e6fc86583b0c7e363ce90fe3ca3e7", + "url": "https://api.github.com/repos/symfony/validator/zipball/7c3897b7f739d4ab913481e680405ca82d08084d", + "reference": "7c3897b7f739d4ab913481e680405ca82d08084d", "shasum": "" }, "require": { @@ -10454,7 +10455,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.31" + "source": "https://github.com/symfony/validator/tree/v6.4.34" }, "funding": [ { @@ -10474,20 +10475,20 @@ "type": "tidelift" } ], - "time": "2025-12-24T09:35:58+00:00" + "time": "2026-02-23T17:49:24+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.26", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a" + "reference": "131fc9915e0343052af5ed5040401b481ca192aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cfae1497a2f1eaad78dbc0590311c599c7178d4a", - "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/131fc9915e0343052af5ed5040401b481ca192aa", + "reference": "131fc9915e0343052af5ed5040401b481ca192aa", "shasum": "" }, "require": { @@ -10542,7 +10543,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.26" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.32" }, "funding": [ { @@ -10562,7 +10563,7 @@ "type": "tidelift" } ], - "time": "2025-09-25T15:37:27+00:00" + "time": "2026-01-01T13:34:06+00:00" }, { "name": "symfony/var-exporter", @@ -10647,16 +10648,16 @@ }, { "name": "symfony/web-link", - "version": "v6.4.24", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a" + "reference": "636d5e34cd5c4a2538b02ba48a3c02989bfdf06b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/75ffbb304f26a716969863328c8c6a11eadcfa5a", - "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a", + "url": "https://api.github.com/repos/symfony/web-link/zipball/636d5e34cd5c4a2538b02ba48a3c02989bfdf06b", + "reference": "636d5e34cd5c4a2538b02ba48a3c02989bfdf06b", "shasum": "" }, "require": { @@ -10710,7 +10711,7 @@ "push" ], "support": { - "source": "https://github.com/symfony/web-link/tree/v6.4.24" + "source": "https://github.com/symfony/web-link/tree/v6.4.32" }, "funding": [ { @@ -10730,20 +10731,20 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-01-01T13:45:34+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.30", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "8207ae83da19ee3748d6d4f567b4d9a7c656e331" + "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/8207ae83da19ee3748d6d4f567b4d9a7c656e331", - "reference": "8207ae83da19ee3748d6d4f567b4d9a7c656e331", + "url": "https://api.github.com/repos/symfony/yaml/zipball/7bca30dabed7900a08c5ad4f1d6483f881a64d0f", + "reference": "7bca30dabed7900a08c5ad4f1d6483f881a64d0f", "shasum": "" }, "require": { @@ -10786,7 +10787,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.30" + "source": "https://github.com/symfony/yaml/tree/v6.4.34" }, "funding": [ { @@ -10806,20 +10807,20 @@ "type": "tidelift" } ], - "time": "2025-12-02T11:50:18+00:00" + "time": "2026-02-06T18:32:11+00:00" }, { "name": "twig/twig", - "version": "v3.22.2", + "version": "v3.23.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2" + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/946ddeafa3c9f4ce279d1f34051af041db0e16f2", - "reference": "946ddeafa3c9f4ce279d1f34051af041db0e16f2", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", + "reference": "a64dc5d2cc7d6cafb9347f6cd802d0d06d0351c9", "shasum": "" }, "require": { @@ -10873,7 +10874,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.22.2" + "source": "https://github.com/twigphp/Twig/tree/v3.23.0" }, "funding": [ { @@ -10885,7 +10886,7 @@ "type": "tidelift" } ], - "time": "2025-12-14T11:28:47+00:00" + "time": "2026-01-23T21:00:41+00:00" }, { "name": "vich/uploader-bundle", @@ -11391,16 +11392,16 @@ }, { "name": "ergebnis/composer-normalize", - "version": "2.48.2", + "version": "2.50.0", "source": { "type": "git", "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" + "reference": "80971fe24ff10709789942bcbe9368b2c704097c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", - "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/80971fe24ff10709789942bcbe9368b2c704097c", + "reference": "80971fe24ff10709789942bcbe9368b2c704097c", "shasum": "" }, "require": { @@ -11414,20 +11415,20 @@ "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" }, "require-dev": { - "composer/composer": "^2.8.3", + "composer/composer": "^2.9.4", "ergebnis/license": "^2.7.0", - "ergebnis/php-cs-fixer-config": "^6.53.0", - "ergebnis/phpstan-rules": "^2.11.0", + "ergebnis/php-cs-fixer-config": "^6.59.0", + "ergebnis/phpstan-rules": "^2.13.1", "ergebnis/phpunit-slow-test-detector": "^2.20.0", + "ergebnis/rector-rules": "^1.9.0", "fakerphp/faker": "^1.24.1", - "infection/infection": "~0.26.6", "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.17", + "phpstan/phpstan": "^2.1.38", "phpstan/phpstan-deprecation-rules": "^2.0.3", - "phpstan/phpstan-phpunit": "^2.0.7", - "phpstan/phpstan-strict-rules": "^2.0.6", - "phpunit/phpunit": "^9.6.20", - "rector/rector": "^2.1.4", + "phpstan/phpstan-phpunit": "^2.0.12", + "phpstan/phpstan-strict-rules": "^2.0.8", + "phpunit/phpunit": "^9.6.33", + "rector/rector": "^2.3.5", "symfony/filesystem": "^5.4.41" }, "type": "composer-plugin", @@ -11471,7 +11472,7 @@ "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2025-09-06T11:42:34+00:00" + "time": "2026-02-09T20:57:47+00:00" }, { "name": "ergebnis/json", @@ -12523,11 +12524,11 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.32", + "version": "1.12.33", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", - "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1", + "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1", "shasum": "" }, "require": { @@ -12572,7 +12573,7 @@ "type": "github" } ], - "time": "2025-09-30T10:16:31+00:00" + "time": "2026-02-28T20:30:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -12895,16 +12896,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.31", + "version": "9.6.34", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "945d0b7f346a084ce5549e95289962972c4272e5" + "reference": "b36f02317466907a230d3aa1d34467041271ef4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/945d0b7f346a084ce5549e95289962972c4272e5", - "reference": "945d0b7f346a084ce5549e95289962972c4272e5", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a", + "reference": "b36f02317466907a230d3aa1d34467041271ef4a", "shasum": "" }, "require": { @@ -12926,7 +12927,7 @@ "phpunit/php-timer": "^5.0.3", "sebastian/cli-parser": "^1.0.2", "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.9", + "sebastian/comparator": "^4.0.10", "sebastian/diff": "^4.0.6", "sebastian/environment": "^5.1.5", "sebastian/exporter": "^4.0.8", @@ -12978,7 +12979,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.31" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34" }, "funding": [ { @@ -13002,7 +13003,7 @@ "type": "tidelift" } ], - "time": "2025-12-06T07:45:52+00:00" + "time": "2026-01-27T05:45:00+00:00" }, { "name": "psalm/plugin-symfony", @@ -13297,16 +13298,16 @@ }, { "name": "sebastian/comparator", - "version": "4.0.9", + "version": "4.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5" + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/67a2df3a62639eab2cc5906065e9805d4fd5dfc5", - "reference": "67a2df3a62639eab2cc5906065e9805d4fd5dfc5", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", + "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", "shasum": "" }, "require": { @@ -13359,7 +13360,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.9" + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" }, "funding": [ { @@ -13379,7 +13380,7 @@ "type": "tidelift" } ], - "time": "2025-08-10T06:51:50+00:00" + "time": "2026-01-24T09:22:56+00:00" }, { "name": "sebastian/complexity", @@ -14143,16 +14144,16 @@ }, { "name": "symfony/browser-kit", - "version": "v6.4.31", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "5b8564c882ca8eb9a06ed2840abc9b2a40f1e12a" + "reference": "f49947cf0cbd7d685281ef74e05b98f5e75b181f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/5b8564c882ca8eb9a06ed2840abc9b2a40f1e12a", - "reference": "5b8564c882ca8eb9a06ed2840abc9b2a40f1e12a", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/f49947cf0cbd7d685281ef74e05b98f5e75b181f", + "reference": "f49947cf0cbd7d685281ef74e05b98f5e75b181f", "shasum": "" }, "require": { @@ -14191,7 +14192,7 @@ "description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/browser-kit/tree/v6.4.31" + "source": "https://github.com/symfony/browser-kit/tree/v6.4.32" }, "funding": [ { @@ -14211,20 +14212,20 @@ "type": "tidelift" } ], - "time": "2025-12-12T07:51:57+00:00" + "time": "2026-01-13T10:09:10+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.24", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "9b784413143701aa3c94ac1869a159a9e53e8761" + "reference": "b0314c186f1464de048cce58979ff1625ca88bbb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/9b784413143701aa3c94ac1869a159a9e53e8761", - "reference": "9b784413143701aa3c94ac1869a159a9e53e8761", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b0314c186f1464de048cce58979ff1625ca88bbb", + "reference": "b0314c186f1464de048cce58979ff1625ca88bbb", "shasum": "" }, "require": { @@ -14260,7 +14261,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.24" + "source": "https://github.com/symfony/css-selector/tree/v6.4.34" }, "funding": [ { @@ -14280,7 +14281,7 @@ "type": "tidelift" } ], - "time": "2025-07-10T08:14:14+00:00" + "time": "2026-02-16T08:37:21+00:00" }, { "name": "symfony/debug-bundle", @@ -14543,16 +14544,16 @@ }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.27", + "version": "v6.4.34", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa" + "reference": "848bc5d5745500f855bb201d57ae066fd7e67448" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", - "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/848bc5d5745500f855bb201d57ae066fd7e67448", + "reference": "848bc5d5745500f855bb201d57ae066fd7e67448", "shasum": "" }, "require": { @@ -14605,7 +14606,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.27" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.34" }, "funding": [ { @@ -14625,7 +14626,7 @@ "type": "tidelift" } ], - "time": "2025-10-05T13:55:43+00:00" + "time": "2026-02-05T15:19:06+00:00" }, { "name": "theofidry/alice-data-fixtures", @@ -14890,37 +14891,37 @@ }, { "name": "vincentlanglet/twig-cs-fixer", - "version": "3.11.0", + "version": "3.14.0", "source": { "type": "git", "url": "https://github.com/VincentLanglet/Twig-CS-Fixer.git", - "reference": "866af065fd09980b6390ee5c69e45b08053101e8" + "reference": "599f110f192c31af5deb5736d6c1a970afdf51f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/866af065fd09980b6390ee5c69e45b08053101e8", - "reference": "866af065fd09980b6390ee5c69e45b08053101e8", + "url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/599f110f192c31af5deb5736d6c1a970afdf51f3", + "reference": "599f110f192c31af5deb5736d6c1a970afdf51f3", "shasum": "" }, "require": { "composer-runtime-api": "^2.0.0", "ext-ctype": "*", - "ext-json": "*", - "php": ">=8.0", + "php": ">=8.1", "symfony/console": "^5.4.9 || ^6.4 || ^7.0 || ^8.0", "symfony/filesystem": "^5.4 || ^6.4 || ^7.0 || ^8.0", "symfony/finder": "^5.4 || ^6.4 || ^7.0 || ^8.0", "symfony/string": "^5.4.42 || ^6.4.10 || ~7.0.10 || ^7.1.3 || ^8.0", "twig/twig": "^3.4", - "webmozart/assert": "^1.10" + "webmozart/assert": "^1.10 || ^2.0" }, "require-dev": { "composer/semver": "^3.2.0", "dereuromark/composer-prefer-lowest": "^0.1.10", "ergebnis/composer-normalize": "^2.29", "friendsofphp/php-cs-fixer": "^3.13.0", - "infection/infection": "^0.26.16 || ^0.29.14", + "infection/infection": "^0.26.16 || ^0.32.0", "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", "phpstan/phpstan-phpunit": "^2.0", "phpstan/phpstan-strict-rules": "^2.0", "phpstan/phpstan-symfony": "^2.0", @@ -14955,7 +14956,7 @@ "homepage": "https://github.com/VincentLanglet/Twig-CS-Fixer", "support": { "issues": "https://github.com/VincentLanglet/Twig-CS-Fixer/issues", - "source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/3.11.0" + "source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/3.14.0" }, "funding": [ { @@ -14963,7 +14964,7 @@ "type": "github" } ], - "time": "2025-11-24T18:13:18+00:00" + "time": "2026-02-23T13:21:35+00:00" }, { "name": "weirdan/doctrine-psalm-plugin", From 2492e2169665f25b2baef7686b4884e91a58d01e Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:28:00 +0100 Subject: [PATCH 44/47] 6592: Added changes from admin --- .../admin/components/slide/slide-manager.jsx | 19 +-- .../components/slide/slide-media-utils.js | 61 +++++++++ .../admin/admin-slide-media-sync.spec.js | 116 ++++++++++++++++++ docs/v2-changelogs/admin.md | 5 + 4 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 assets/admin/components/slide/slide-media-utils.js create mode 100644 assets/tests/admin/admin-slide-media-sync.spec.js diff --git a/assets/admin/components/slide/slide-manager.jsx b/assets/admin/components/slide/slide-manager.jsx index 4ff804386..542ac6dc0 100644 --- a/assets/admin/components/slide/slide-manager.jsx +++ b/assets/admin/components/slide/slide-manager.jsx @@ -4,6 +4,7 @@ import { ulid } from "ulid"; import { useDispatch } from "react-redux"; import dayjs from "dayjs"; import { useNavigate } from "react-router-dom"; +import rebuildMediaFromContent from "./slide-media-utils"; import UserContext from "../../context/user-context"; import { enhancedApi, @@ -337,13 +338,11 @@ function SlideManager({ const localFormStateObject = { ...formStateObject }; const localMediaData = { ...mediaData }; // Set field as a field to look into for new references. - setMediaFields([...new Set([...mediaFields, fieldId])]); + const updatedMediaFields = [...new Set([...mediaFields, fieldId])]; + setMediaFields(updatedMediaFields); const newField = []; - if (Array.isArray(fieldValue) && fieldValue.length === 0) { - localFormStateObject.media = []; - } // Handle each entry in field. if (Array.isArray(fieldValue)) { fieldValue.forEach((entry) => { @@ -383,17 +382,19 @@ function SlideManager({ !Object.prototype.hasOwnProperty.call(localMediaData, entry["@id"]) ) { set(localMediaData, entry["@id"], entry); - - localFormStateObject.media.push(entry["@id"]); } } }); } set(localFormStateObject.content, fieldId, newField); - set(localFormStateObject, "media", [ - ...new Set([...localFormStateObject.media]), - ]); + + // Rebuild the media array from all content fields to keep it in sync. + set( + localFormStateObject, + "media", + rebuildMediaFromContent(localFormStateObject.content) + ); setFormStateObject(localFormStateObject); setMediaData(localMediaData); diff --git a/assets/admin/components/slide/slide-media-utils.js b/assets/admin/components/slide/slide-media-utils.js new file mode 100644 index 000000000..8c78bfb41 --- /dev/null +++ b/assets/admin/components/slide/slide-media-utils.js @@ -0,0 +1,61 @@ +/** + * Rebuild the media array from all content fields that reference media. + * + * This ensures that the top-level `media` array (sent to the API as slide_media + * associations) always matches the media actually referenced in the slide's + * `content` object. + * + * @param {object} content - The slide content object. + * @returns {string[]} Deduplicated array of media IRIs. + */ +export default function rebuildMediaFromContent(content) { + const media = []; + + const mediaIriRegex = /\/v2\/media\/.+/; + + const isMediaIri = (value) => + typeof value === "string" && + !value.startsWith("TEMP--") && + mediaIriRegex.test(value); + + const collectMediaFromValue = (value, seen = new Set()) => { + // 1) Ignore empty values early (nothing to scan) + if (value === null || value === undefined) return; + + // 2) If it's a string, it might be a media IRI; validate and collect it + if (typeof value === "string") { + if (isMediaIri(value)) media.push(value); + return; + } + + // 3) If it's not an object (e.g. number/boolean/function), it cannot contain nested media + if (typeof value !== "object") return; + + // 4) Defensive guard against circular references: + // - JSON content won't have cycles, but runtime objects might. + // - If we've seen this object/array already, stop to avoid infinite recursion. + if (seen.has(value)) return; + seen.add(value); + + // 5) If it's an array, scan each element (elements can be strings, objects, or more arrays) + if (Array.isArray(value)) { + value.forEach((item) => collectMediaFromValue(item, seen)); + return; + } + + // 6) Otherwise it's a plain object: scan its property values recursively + Object.values(value).forEach((item) => collectMediaFromValue(item, seen)); + }; + + const fieldsToScan = new Set([]); + + // Scan content for media references. + if (content && typeof content === "object") { + Object.keys(content).forEach((key) => fieldsToScan.add(key)); + } + + // Scan the entire content object (one traversal) + collectMediaFromValue(content); + + return [...new Set(media)]; +} diff --git a/assets/tests/admin/admin-slide-media-sync.spec.js b/assets/tests/admin/admin-slide-media-sync.spec.js new file mode 100644 index 000000000..f8e939ca5 --- /dev/null +++ b/assets/tests/admin/admin-slide-media-sync.spec.js @@ -0,0 +1,116 @@ +import { test, expect } from "@playwright/test"; +import rebuildMediaFromContent from "../src/components/slide/slide-media-utils"; + +test.describe("Slide media sync", () => { + test("It returns media IRIs referenced in content fields", () => { + const content = { + mainImage: ["/v2/media/1", "/v2/media/2"], + backgroundVideo: ["/v2/media/3"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/1", "/v2/media/2", "/v2/media/3"]); + }); + + test("It excludes TEMP-- IDs that have not been uploaded yet", () => { + const content = { + mainImage: ["TEMP--abc123", "/v2/media/1"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/1"]); + }); + + test("It removes media no longer referenced in any content field", () => { + const content = { + mainImage: ["/v2/media/2"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/2"]); + expect(result).not.toContain("/v2/media/1"); + }); + + test("It returns empty array when all media is removed from content", () => { + const content = { + mainImage: [], + backgroundVideo: ["/v2/media/3"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/3"]); + }); + + test("It deduplicates media used across multiple content fields", () => { + const content = { + mainImage: ["/v2/media/1"], + thumbnail: ["/v2/media/1"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/1"]); + }); + + test("It handles non-existent content fields gracefully", () => { + const content = {}; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual([]); + }); + + test("It handles nested content field paths", () => { + const content = { + sections: { + hero: ["/v2/media/1"], + }, + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/1"]); + }); + + test("It ignores non-media content values when scanning top-level keys", () => { + const content = { + images: ["/v2/media/1"], + title: "Some text", + separator: true, + contacts: [{ name: "John", image: ["/v2/media/2"], tags: ["news"] }], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toContain("/v2/media/1"); + expect(result).toContain("/v2/media/2"); + expect(result).not.toContain("news"); + }); + + test("It does not include non-media string arrays from content", () => { + const content = { + images: ["/v2/media/1"], + tags: ["news", "sports"], + }; + + const result = rebuildMediaFromContent(content); + + expect(result).toEqual(["/v2/media/1"]); + expect(result).not.toContain("news"); + expect(result).not.toContain("sports"); + }); + + test("It avoids infinite recursion when content contains circular references", () => { + const circular = { images: ["/v2/media/1"] }; + circular.self = circular; // create an explicit cycle + + expect(() => rebuildMediaFromContent(circular)).not.toThrow(); + + const result = rebuildMediaFromContent(circular); + expect(result).toContain("/v2/media/1"); + }); +}); diff --git a/docs/v2-changelogs/admin.md b/docs/v2-changelogs/admin.md index fdb6189a9..861678f6c 100644 --- a/docs/v2-changelogs/admin.md +++ b/docs/v2-changelogs/admin.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.6.1] - 2026-03-06 + +- [#295](https://github.com/os2display/display-admin-client/pull/295) + - Fixed slide media array not syncing with content on media removal. + ## [2.6.0] - 2025-12-05 - [#293](https://github.com/os2display/display-admin-client/pull/293) From 6f472ca62d600c794c5fb47f059f56999d2caf91 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:36:02 +0100 Subject: [PATCH 45/47] 6592: Added changes to templates --- assets/shared/templates/image-text.jsx | 41 ++++++++++++++++---------- docs/v2-changelogs/template.md | 5 ++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/assets/shared/templates/image-text.jsx b/assets/shared/templates/image-text.jsx index de32bd6d6..bcad1bd81 100644 --- a/assets/shared/templates/image-text.jsx +++ b/assets/shared/templates/image-text.jsx @@ -42,6 +42,7 @@ function renderSlide(slide, run, slideDone) { */ function ImageText({ slide, content, run, slideDone, executionId }) { const imageTimeoutRef = useRef(); + const imagesRef = useRef([]); const [images, setImages] = useState([]); const [currentImage, setCurrentImage] = useState(); const logo = slide?.theme?.logo; @@ -132,13 +133,15 @@ function ImageText({ slide, content, run, slideDone, executionId }) { } const changeImage = (newIndex) => { - if (newIndex < images.length) { - setCurrentImage(images[newIndex]); + const currentImages = imagesRef.current; - if (newIndex < images.length - 1) { + if (newIndex < currentImages.length) { + setCurrentImage(currentImages[newIndex]); + + if (newIndex < currentImages.length - 1) { imageTimeoutRef.current = setTimeout( () => changeImage(newIndex + 1), - duration / images.length, + duration / currentImages.length ); } } @@ -152,33 +155,41 @@ function ImageText({ slide, content, run, slideDone, executionId }) { ); if (imageUrls?.length > 0) { - const newImages = imageUrls.map((url) => { - return { - url, - nodeRef: createRef(), - }; - }); + const newImages = imageUrls.map((url) => ({ + url, + nodeRef: createRef(), + })); + + imagesRef.current = newImages; setImages(newImages); + } else { + imagesRef.current = []; + setImages([]); } } }, [slide]); const startTheShow = () => { - if (images?.length > 0 && !currentImage) { - setCurrentImage(images[0]); + if (imageTimeoutRef.current) { + clearTimeout(imageTimeoutRef.current); } - // If there are multiple images, we are going to loop through these WITHIN the set duration. - if (images?.length > 1) { + const currentImages = imagesRef.current; + + if (currentImages.length > 1) { // Kickoff the display of multiple images with the zero indexed changeImage(0); + } else if (currentImages.length === 1) { + setCurrentImage(currentImages[0]); } }; useEffect(() => { - if (!currentImage) { + if (images.length > 0) { startTheShow(); + } else { + setCurrentImage(undefined); } }, [images]); diff --git a/docs/v2-changelogs/template.md b/docs/v2-changelogs/template.md index 43ab7f98a..793c82992 100644 --- a/docs/v2-changelogs/template.md +++ b/docs/v2-changelogs/template.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. ## Unreleased +## [2.6.1] - 2026-03-06 + +- [#196](https://github.com/os2display/display-templates/pull/196) + - Fixed image-text carousel not updating when images array changes. + ## [2.6.0] - 2025-12-05 - [#194](https://github.com/os2display/display-templates/pull/194) From b2155f4628bae6024493f85293c36e9d04f3ab3e Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:41:17 +0100 Subject: [PATCH 46/47] 6592: Applied coding standards --- assets/admin/components/slide/slide-manager.jsx | 2 +- assets/shared/templates/image-text.jsx | 2 +- src/Controller/Api/InteractiveController.php | 2 +- src/Feed/CalendarApiFeedType.php | 4 ++-- src/Feed/EventDatabaseApiV2FeedType.php | 8 ++++---- src/Feed/KobaFeedType.php | 3 +-- src/Repository/PlaylistSlideRepository.php | 4 ++-- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/assets/admin/components/slide/slide-manager.jsx b/assets/admin/components/slide/slide-manager.jsx index 542ac6dc0..eeee9320b 100644 --- a/assets/admin/components/slide/slide-manager.jsx +++ b/assets/admin/components/slide/slide-manager.jsx @@ -393,7 +393,7 @@ function SlideManager({ set( localFormStateObject, "media", - rebuildMediaFromContent(localFormStateObject.content) + rebuildMediaFromContent(localFormStateObject.content), ); setFormStateObject(localFormStateObject); diff --git a/assets/shared/templates/image-text.jsx b/assets/shared/templates/image-text.jsx index bcad1bd81..6f6b33baa 100644 --- a/assets/shared/templates/image-text.jsx +++ b/assets/shared/templates/image-text.jsx @@ -141,7 +141,7 @@ function ImageText({ slide, content, run, slideDone, executionId }) { if (newIndex < currentImages.length - 1) { imageTimeoutRef.current = setTimeout( () => changeImage(newIndex + 1), - duration / currentImages.length + duration / currentImages.length, ); } } diff --git a/src/Controller/Api/InteractiveController.php b/src/Controller/Api/InteractiveController.php index edd3ee460..6cdde602a 100644 --- a/src/Controller/Api/InteractiveController.php +++ b/src/Controller/Api/InteractiveController.php @@ -35,7 +35,7 @@ public function __invoke(Request $request, Slide $slide): JsonResponse { $user = $this->security->getUser(); - if (!($user instanceof ScreenUser)) { + if (!$user instanceof ScreenUser) { throw new AccessDeniedHttpException('Only screen user can perform action.'); } diff --git a/src/Feed/CalendarApiFeedType.php b/src/Feed/CalendarApiFeedType.php index 3b0a7ed0b..8f5393ffe 100644 --- a/src/Feed/CalendarApiFeedType.php +++ b/src/Feed/CalendarApiFeedType.php @@ -461,9 +461,9 @@ private function parseBool(string|bool $value): bool { if (is_bool($value)) { return $value; - } else { - return 'true' == strtolower($value); } + + return 'true' == strtolower($value); } private function getMapping(string $key): string diff --git a/src/Feed/EventDatabaseApiV2FeedType.php b/src/Feed/EventDatabaseApiV2FeedType.php index e24e002f7..3f552f571 100644 --- a/src/Feed/EventDatabaseApiV2FeedType.php +++ b/src/Feed/EventDatabaseApiV2FeedType.php @@ -165,9 +165,9 @@ public function getData(Feed $feed): array // Fallback option is to return the cached data. if ($cacheItem->isHit()) { return $cacheItem->get(); - } else { - return []; } + + return []; } /** @@ -281,9 +281,9 @@ public function getConfigOptions(Request $request, FeedSource $feedSource, strin } catch (\Exception) { if ($cacheItem->isHit()) { return $cacheItem->get(); - } else { - return []; } + + return []; } } elseif ('subscription' === $name) { $query = $request->query->all(); diff --git a/src/Feed/KobaFeedType.php b/src/Feed/KobaFeedType.php index aab326081..db4bd10ec 100644 --- a/src/Feed/KobaFeedType.php +++ b/src/Feed/KobaFeedType.php @@ -88,9 +88,8 @@ public function getData(Feed $feed): array if (true === $filterList) { if (!str_contains($title, '(liste)')) { continue; - } else { - $title = str_replace('(liste)', '', $title); } + $title = str_replace('(liste)', '', $title); } // Apply booked title override. If enabled it changes the title to Optaget if it contains (optaget). diff --git a/src/Repository/PlaylistSlideRepository.php b/src/Repository/PlaylistSlideRepository.php index 8987f6797..a084f6a50 100644 --- a/src/Repository/PlaylistSlideRepository.php +++ b/src/Repository/PlaylistSlideRepository.php @@ -216,8 +216,8 @@ private function getWeight(Ulid $ulid): int $playlistSlide = $queryBuilder->getQuery()->setMaxResults(1)->execute(); if (0 === count($playlistSlide)) { return 0; - } else { - return $playlistSlide[0]->getWeight() + 1; } + + return $playlistSlide[0]->getWeight() + 1; } } From 2d3b0ef56d6a0f5f2f0ae302fdc6944054d0e742 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:48:20 +0100 Subject: [PATCH 47/47] 6592: Fixed import path --- assets/tests/admin/admin-slide-media-sync.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/tests/admin/admin-slide-media-sync.spec.js b/assets/tests/admin/admin-slide-media-sync.spec.js index f8e939ca5..6f8164888 100644 --- a/assets/tests/admin/admin-slide-media-sync.spec.js +++ b/assets/tests/admin/admin-slide-media-sync.spec.js @@ -1,5 +1,5 @@ import { test, expect } from "@playwright/test"; -import rebuildMediaFromContent from "../src/components/slide/slide-media-utils"; +import rebuildMediaFromContent from "../../admin/components/slide/slide-media-utils"; test.describe("Slide media sync", () => { test("It returns media IRIs referenced in content fields", () => {