From 894b20dd749d7d22e6065060ccefb580084daf2f Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 5 Sep 2025 11:21:13 +0200 Subject: [PATCH 01/38] 5402: Remove unmaintained infrastructure code for os2display images --- infrastructure/os2display/Readme.md | 3 - .../os2display/display-api-service/Dockerfile | 155 ------------------ .../display-api-service/docker-entrypoint.sh | 22 --- .../etc/confd/conf.d/env.local.toml | 8 - .../etc/confd/templates/env.local.tmpl | 71 -------- .../os2display/display-api-service/gitconfig | 9 - .../display-api-service/php/apcu.ini | 7 - .../display-api-service/php/fpm.ini | 17 -- .../display-api-service/php/opcache.ini | 15 -- .../display-api-service/php/php.ini | 13 -- infrastructure/os2display/nginx/Dockerfile | 37 ----- .../os2display/nginx/docker-entrypoint.sh | 49 ------ .../nginx/etc/confd/conf.d/default.conf.toml | 7 - .../nginx/etc/confd/conf.d/nginx.conf.toml | 7 - .../etc/confd/templates/default.conf.tmpl | 52 ------ .../nginx/etc/confd/templates/nginx.conf.tmpl | 51 ------ infrastructure/os2display/run.sh | 13 -- 17 files changed, 536 deletions(-) delete mode 100644 infrastructure/os2display/Readme.md delete mode 100644 infrastructure/os2display/display-api-service/Dockerfile delete mode 100644 infrastructure/os2display/display-api-service/docker-entrypoint.sh delete mode 100644 infrastructure/os2display/display-api-service/etc/confd/conf.d/env.local.toml delete mode 100644 infrastructure/os2display/display-api-service/etc/confd/templates/env.local.tmpl delete mode 100644 infrastructure/os2display/display-api-service/gitconfig delete mode 100644 infrastructure/os2display/display-api-service/php/apcu.ini delete mode 100644 infrastructure/os2display/display-api-service/php/fpm.ini delete mode 100644 infrastructure/os2display/display-api-service/php/opcache.ini delete mode 100644 infrastructure/os2display/display-api-service/php/php.ini delete mode 100644 infrastructure/os2display/nginx/Dockerfile delete mode 100644 infrastructure/os2display/nginx/docker-entrypoint.sh delete mode 100644 infrastructure/os2display/nginx/etc/confd/conf.d/default.conf.toml delete mode 100644 infrastructure/os2display/nginx/etc/confd/conf.d/nginx.conf.toml delete mode 100644 infrastructure/os2display/nginx/etc/confd/templates/default.conf.tmpl delete mode 100644 infrastructure/os2display/nginx/etc/confd/templates/nginx.conf.tmpl delete mode 100755 infrastructure/os2display/run.sh diff --git a/infrastructure/os2display/Readme.md b/infrastructure/os2display/Readme.md deleted file mode 100644 index def6e8a45..000000000 --- a/infrastructure/os2display/Readme.md +++ /dev/null @@ -1,3 +0,0 @@ -# OS2display image build - -This folder contains the infrastructure files for building the `os2display/*` images diff --git a/infrastructure/os2display/display-api-service/Dockerfile b/infrastructure/os2display/display-api-service/Dockerfile deleted file mode 100644 index 2809349f8..000000000 --- a/infrastructure/os2display/display-api-service/Dockerfile +++ /dev/null @@ -1,155 +0,0 @@ -FROM php:8.3-fpm-alpine -LABEL maintainer="ITK Dev " - -############# SETUP CONTAINER ############# - -USER root - -ARG APP_VERSION="develop" - -ENV APP_PATH=/var/www/html \ - # PHP - TZ="Europe/Copenhagen" \ - PHP_TIMEZONE="Europe/Copenhagen" \ - PHP_MAX_EXECUTION_TIME="30" \ - PHP_MEMORY_LIMIT="128M" \ - PHP_POST_MAX_SIZE="8M" \ - PHP_UPLOAD_MAX_FILESIZE="2M" \ - PHP_USER="www-data" \ - PHP_GROUP="www-data" \ - PHP_SENDMAIL_PATH='/usr/sbin/sendmail -S host.docker.internal -t -i' \ - # OpCache - PHP_OPCACHE_ENABLED="1" \ - PHP_OPCACHE_JIT="off" \ - PHP_OPCACHE_REVALIDATE_FREQ=0 \ - PHP_OPCACHE_VALIDATE_TIMESTAMPS="1" \ - PHP_OPCACHE_MAX_ACCELERATED_FILES="20000" \ - PHP_OPCACHE_MEMORY_CONSUMPTION="64" \ - PHP_OPCACHE_MAX_WASTED_PERCENTAGE="10" \ - # APCU - PHP_APCU_ENABLED=0 \ - PHP_APCU_ENABLED_CLI=0 \ - PHP_APCU_MEMORY_SIZE="16M" \ - PHP_APCU_SEGMENTS=1 \ - PHP_APCU_PRELOAD_PATH='' \ - # FPM pool - PHP_PM_TYPE="static" \ - PHP_PM_MAX_CHILDREN="8" \ - PHP_PM_MAX_REQUESTS="0" \ - PHP_PM_START_SERVERS="5" \ - PHP_PM_MIN_SPARE_SERVERS="5" \ - PHP_PM_MAX_SPARE_SERVERS="8" \ - # Other - PHP_REQUEST_SLOWLOG_TIMEOUT="0" \ - PHP_SLOWLOG="/dev/stderr" \ - COMPOSER_ALLOW_SUPERUSER=1 - -RUN apk upgrade --no-cache --ignore curl -RUN apk --update add --no-cache \ - libxslt-dev \ - libzip-dev \ - libpng-dev \ - gettext-dev \ - git \ - unzip \ - icu-dev \ - icu-data-full \ - openldap-dev \ - libmcrypt-dev \ - mysql-client \ - libmemcached-libs \ - zlib \ - patch \ - tzdata \ - freetype-dev \ - libjpeg-turbo-dev \ - libjpeg-turbo \ - libwebp-dev \ - && docker-php-ext-configure gd --with-freetype --with-webp --with-jpeg \ - && docker-php-ext-install -j$(nproc) \ - bcmath \ - calendar \ - gd \ - gettext \ - intl \ - ldap \ - mysqli \ - opcache \ - pdo_mysql \ - sysvsem \ - soap \ - xsl \ - zip - -# Extension that are not available via ext- -RUN apk --update add --no-cache --virtual .build-deps autoconf g++ make zlib-dev libmemcached-dev cyrus-sasl-dev \ - && pecl channel-update pecl.php.net \ - && pecl install redis memcached apcu \ - && docker-php-ext-enable apcu redis memcached \ - && apk del .build-deps - -# Install AMQP support -RUN apk --update add --no-cache rabbitmq-c -RUN apk --update add --no-cache --virtual .build-deps autoconf g++ make rabbitmq-c-dev \ - && pecl install amqp \ - && docker-php-ext-enable amqp memcached \ - && apk del .build-deps - -# Install composer -COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer - -# Use default PHP production configuration. -RUN mv ${PHP_INI_DIR}/php.ini-production ${PHP_INI_DIR}/php.ini - -# # Copy custom PHP configuration. -COPY php/opcache.ini ${PHP_INI_DIR}/conf.d/docker-php-ext-opcache.ini -COPY php/php.ini ${PHP_INI_DIR}/conf.d/zz-php.ini -COPY php/apcu.ini ${PHP_INI_DIR}/conf.d/docker-php-ext-apcu.ini - -# Custom FPM configuration. -COPY php/fpm.ini ${PHP_INI_DIR}/../php-fpm.d/zz-fpm-docker.conf - -# Add mhsendmail for mailhog -ADD https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 /usr/local/bin/mhsendmail -RUN chmod +x /usr/local/bin/mhsendmail - -# Added FPM health check script (https://github.com/renatomefi/php-fpm-healthcheck) -ADD https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/master/php-fpm-healthcheck /usr/local/bin/php-fpm-healthcheck -RUN chmod +x /usr/local/bin/php-fpm-healthcheck - -# Add git global config -COPY gitconfig /root/.gitconfig - -############# SETUP APPLICATION ############# - -# Move site into the container. -ADD https://github.com/os2display/display-api-service/archive/${APP_VERSION}.tar.gz /tmp/app.tar -RUN tar -zxf /tmp/app.tar --strip-components=1 -C ${APP_PATH} \ - && rm /tmp/app.tar - -## Install assets, which requires a HACK as redis is not available (should be removed later on). -RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative \ - && rm -rf infrastructure \ - && APP_ENV=prod composer clear-cache - -# Install the application. -RUN mkdir -p ${APP_PATH}/config/secrets \ - && chown -R www-data:www-data ${APP_PATH} - -# Copy configuration. -COPY etc /etc/ - -# Install configuration template handler -ADD https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 /usr/local/bin/confd -RUN chmod +x /usr/local/bin/confd - -# Copy confd onfiguration. -COPY etc /etc/ - -COPY docker-entrypoint.sh /usr/local/bin/ -RUN chmod +x /usr/local/bin/docker-entrypoint.sh - -WORKDIR ${APP_PATH} - -CMD ["php-fpm"] -ENTRYPOINT [ "docker-entrypoint.sh" ] diff --git a/infrastructure/os2display/display-api-service/docker-entrypoint.sh b/infrastructure/os2display/display-api-service/docker-entrypoint.sh deleted file mode 100644 index 8ad622b4d..000000000 --- a/infrastructure/os2display/display-api-service/docker-entrypoint.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/sh - -set -eux - -## Run templates with configuration. -/usr/local/bin/confd --onetime --backend env --confdir /etc/confd - -## Bump env.local into PHP for better performance. -composer dump-env prod - -## Warm-up Symfony cache (with the current configuration). -/var/www/html/bin/console --env=prod cache:warmup - -# first arg is `-f` or `--some-option` -if [ "${1#-}" != "$1" ]; then - set -- php-fpm "$@" -fi - -## Start the PHP FPM process. -echo "Starting PHP 8.3 FPM" - -exec "$@" diff --git a/infrastructure/os2display/display-api-service/etc/confd/conf.d/env.local.toml b/infrastructure/os2display/display-api-service/etc/confd/conf.d/env.local.toml deleted file mode 100644 index e7f303a3e..000000000 --- a/infrastructure/os2display/display-api-service/etc/confd/conf.d/env.local.toml +++ /dev/null @@ -1,8 +0,0 @@ -[template] -src = "env.local.tmpl" -dest = "/var/www/html/.env.local" -owner = "www-data" -mode = "0644" -keys = [ - "/app-config" -] diff --git a/infrastructure/os2display/display-api-service/etc/confd/templates/env.local.tmpl b/infrastructure/os2display/display-api-service/etc/confd/templates/env.local.tmpl deleted file mode 100644 index 1fa420ab2..000000000 --- a/infrastructure/os2display/display-api-service/etc/confd/templates/env.local.tmpl +++ /dev/null @@ -1,71 +0,0 @@ -###> symfony/framework-bundle ### -APP_ENV={{ getenv "APP_ENV" "prod" }} -APP_SECRET={{ getenv "APP_SECRET" "MySuperSecret" }} -TRUSTED_PROXIES={{ getenv "APP_TRUSTED_PROXIES" "127.0.0.1,REMOTE_ADDR" }} -###< symfony/framework-bundle ### - -###> doctrine/doctrine-bundle ### -DATABASE_URL={{ getenv "APP_DATABASE_URL" "mysql://db:db@mariadb:3306/db?serverVersion=mariadb-10.4.0" }} -###< doctrine/doctrine-bundle ### - -###> nelmio/cors-bundle ### -CORS_ALLOW_ORIGIN={{ getenv "APP_CORS_ALLOW_ORIGIN" "'^https?://localhost(:[0-9]+)?$'" }} -###< nelmio/cors-bundle ### - -###> App ### -APP_DEFAULT_DATE_FORMAT='{{ getenv "APP_DEFAULT_DATE_FORMAT" "Y-m-d\\TH:i:s\\Z" }}' -APP_ACTIVATION_CODE_EXPIRE_INTERNAL='{{ getenv "APP_ACTIVATION_CODE_EXPIRE_INTERNAL" "P2D" }}' -###< App ### - -###> lexik/jwt-authentication-bundle ### -JWT_PASSPHRASE={{ getenv "APP_JWT_PASSPHRASE" }} -JWT_TOKEN_TTL={{ getenv "APP_JWT_TOKEN_TTL" "3600" }} -JWT_SCREEN_TOKEN_TTL={{ getenv "APP_JWT_SCREEN_TOKEN_TTL" "3600" }} -###< lexik/jwt-authentication-bundle ### - -###> gesdinet/jwt-refresh-token-bundle ### -JWT_REFRESH_TOKEN_TTL={{ getenv "APP_JWT_REFRESH_TOKEN_TTL" "2592000" }} -JWT_SCREEN_REFRESH_TOKEN_TTL={{ getenv "APP_JWT_SCREEN_REFRESH_TOKEN_TTL" "2592000" }} -###< gesdinet/jwt-refresh-token-bundle ### - -###> itk-dev/openid-connect-bundle ### -# internal provider -INTERNAL_OIDC_METADATA_URL={{ getenv "APP_INTERNAL_OIDC_METADATA_URL" "" }} -INTERNAL_OIDC_CLIENT_ID={{ getenv "APP_INTERNAL_OIDC_CLIENT_ID" "" }} -INTERNAL_OIDC_CLIENT_SECRET={{ getenv "APP_INTERNAL_OIDC_CLIENT_SECRET" "" }} -INTERNAL_OIDC_REDIRECT_URI={{ getenv "APP_INTERNAL_OIDC_REDIRECT_URI" "" }} -INTERNAL_OIDC_LEEWAY={{ getenv "APP_INTERNAL_OIDC_LEEWAY" "30" }} - -# external provider -EXTERNAL_OIDC_METADATA_URL={{ getenv "APP_EXTERNAL_OIDC_METADATA_URL" "" }} -EXTERNAL_OIDC_CLIENT_ID={{ getenv "APP_EXTERNAL_OIDC_CLIENT_ID" "" }} -EXTERNAL_OIDC_CLIENT_SECRET={{ getenv "APP_EXTERNAL_OIDC_CLIENT_SECRET" "" }} -EXTERNAL_OIDC_REDIRECT_URI={{ getenv "APP_EXTERNAL_OIDC_REDIRECT_URI" "" }} -EXTERNAL_OIDC_LEEWAY={{ getenv "APP_EXTERNAL_OIDC_LEEWAY" "30" }} -EXTERNAL_OIDC_HASH_SALT={{ getenv "APP_EXTERNAL_OIDC_HASH_SALT" "" }} - -CLI_REDIRECT={{ getenv "APP_CLI_REDIRECT" "" }} -###< itk-dev/openid-connect-bundle ### - -###> redis ### -REDIS_CACHE_PREFIX={{ getenv "APP_CLI_REDIRECT" "DisplayApiService" }} -REDIS_CACHE_DSN={{ getenv "APP_CLI_REDIRECT" "redis://redis:6379/0" }} -###< redis ### - -###> Calendar Api Feed Source ### -CALENDAR_API_FEED_SOURCE_LOCATION_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_LOCATION_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_RESOURCE_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_RESOURCE_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_EVENT_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_EVENT_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_CUSTOM_MAPPINGS={{ getenv "APP_CALENDAR_API_FEED_SOURCE_CUSTOM_MAPPINGS" "'{}'" }} -CALENDAR_API_FEED_SOURCE_EVENT_MODIFIERS={{ getenv "APP_CALENDAR_API_FEED_SOURCE_EVENT_MODIFIERS" "'{}'" }} -CALENDAR_API_FEED_SOURCE_DATE_FORMAT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_DATE_FORMAT" "" }} -CALENDAR_API_FEED_SOURCE_DATE_TIMEZONE={{ getenv "APP_CALENDAR_API_FEED_SOURCE_DATE_TIMEZONE" "" }} -CALENDAR_API_FEED_SOURCE_CACHE_EXPIRE_SECONDS={{ getenv "CALENDAR_API_FEED_SOURCE_CACHE_EXPIRE_SECONDS" "300" }} -###< Calendar Api Feed Source ### - -EVENTDATABASE_API_V2_CACHE_EXPIRE_SECONDS={{ getenv "APP_EVENTDATABASE_API_V2_CACHE_EXPIRE_SECONDS" "300" }} - -TRACK_SCREEN_INFO={{ getenv "APP_TRACK_SCREEN_INFO" "false" }} -TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS={{ getenv "APP_TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS" "300" }} - -APP_KEY_VAULT_JSON={{ getenv "APP_KEY_VAULT_JSON" "{}" }} diff --git a/infrastructure/os2display/display-api-service/gitconfig b/infrastructure/os2display/display-api-service/gitconfig deleted file mode 100644 index 60a3b0202..000000000 --- a/infrastructure/os2display/display-api-service/gitconfig +++ /dev/null @@ -1,9 +0,0 @@ -[color] - ui = true - -[alias] - branch-name = !git for-each-ref --format='%(refname:short)' `git symbolic-ref HEAD` - lg = log --graph --pretty=format:'%Cred%h%Creset %Cgreen(%cr) -%C(yellow)%d%Creset %s %C(bold blue)<%an>%Creset' --abbrev-commit --date=relative - -[safe] - directory = * \ No newline at end of file diff --git a/infrastructure/os2display/display-api-service/php/apcu.ini b/infrastructure/os2display/display-api-service/php/apcu.ini deleted file mode 100644 index 86164be82..000000000 --- a/infrastructure/os2display/display-api-service/php/apcu.ini +++ /dev/null @@ -1,7 +0,0 @@ -extension=apcu -apc.enabled=${PHP_APCU_ENABLED} -apc.shm_segments=${PHP_APCU_SEGMENTS} -apc.shm_size=${PHP_APCU_MEMORY_SIZE} - -apc.enable_cli=${PHP_APCU_ENABLED_CLI} -apc.preload_path=${PHP_APCU_PRELOAD_PATH} \ No newline at end of file diff --git a/infrastructure/os2display/display-api-service/php/fpm.ini b/infrastructure/os2display/display-api-service/php/fpm.ini deleted file mode 100644 index 49e0aeb48..000000000 --- a/infrastructure/os2display/display-api-service/php/fpm.ini +++ /dev/null @@ -1,17 +0,0 @@ -[www] -pm = ${PHP_PM_TYPE} -pm.max_children = ${PHP_PM_MAX_CHILDREN} -pm.start_servers = ${PHP_PM_START_SERVERS} -pm.min_spare_servers = ${PHP_PM_MIN_SPARE_SERVERS} -pm.max_spare_servers = ${PHP_PM_MAX_SPARE_SERVERS} -pm.max_requests = ${PHP_PM_MAX_REQUESTS} - -request_slowlog_timeout = ${PHP_REQUEST_SLOWLOG_TIMEOUT} -slowlog = ${PHP_SLOWLOG} - -; Enable the FPM status page -pm.status_path = /status - -user = ${PHP_USER} -group = ${PHP_GROUP} - diff --git a/infrastructure/os2display/display-api-service/php/opcache.ini b/infrastructure/os2display/display-api-service/php/opcache.ini deleted file mode 100644 index 8ff178634..000000000 --- a/infrastructure/os2display/display-api-service/php/opcache.ini +++ /dev/null @@ -1,15 +0,0 @@ -zend_extension=opcache.so - -[opcache] -opcache.jit=${PHP_OPCACHE_JIT} - -opcache.enable=${PHP_OPCACHE_ENABLED} -opcache.revalidate_freq=${PHP_OPCACHE_REVALIDATE_FREQ} -opcache.validate_timestamps=${PHP_OPCACHE_VALIDATE_TIMESTAMPS} -opcache.max_accelerated_files=${PHP_OPCACHE_MAX_ACCELERATED_FILES} -opcache.memory_consumption=${PHP_OPCACHE_MEMORY_CONSUMPTION} -opcache.max_wasted_percentage=${PHP_OPCACHE_MAX_WASTED_PERCENTAGE} -opcache.interned_strings_buffer=16 -opcache.fast_shutdown=1 - -opcache.optimization_level=0xFFFFFFEF diff --git a/infrastructure/os2display/display-api-service/php/php.ini b/infrastructure/os2display/display-api-service/php/php.ini deleted file mode 100644 index 2bfde2b40..000000000 --- a/infrastructure/os2display/display-api-service/php/php.ini +++ /dev/null @@ -1,13 +0,0 @@ -realpath_cache_size = 4096k -realpath_cache_ttl = 600 - -expose_php = Off -max_execution_time = ${PHP_MAX_EXECUTION_TIME} -memory_limit = ${PHP_MEMORY_LIMIT} - -post_max_size = ${PHP_POST_MAX_SIZE} -upload_max_filesize = ${PHP_UPLOAD_MAX_FILESIZE} - -date.timezone = ${PHP_TIMEZONE} - -sendmail_path = ${PHP_SENDMAIL_PATH} diff --git a/infrastructure/os2display/nginx/Dockerfile b/infrastructure/os2display/nginx/Dockerfile deleted file mode 100644 index bc13dcd12..000000000 --- a/infrastructure/os2display/nginx/Dockerfile +++ /dev/null @@ -1,37 +0,0 @@ -ARG APP_VERSION="develop" -FROM os2display/display-api-service:${APP_VERSION} as APPLICATION - -FROM nginxinc/nginx-unprivileged:alpine -LABEL maintainer="ITK Dev " -ARG UID=101 -ARG GID=101 - -ENV APP_PATH=/var/www/html - -USER root - -RUN mkdir -p ${APP_PATH}/public - -COPY --from=APPLICATION ${APP_PATH}/public ${APP_PATH}/public - -WORKDIR ${APP_PATH} - -# Copy configuration. -COPY etc /etc/ - -# Install configuration template handler -ADD https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 /usr/local/bin/confd -RUN chmod +x /usr/local/bin/confd - -COPY docker-entrypoint.sh / -RUN chmod +x /docker-entrypoint.sh \ - && chown -R $UID:0 ${APP_PATH} \ - && chmod -R g+w ${APP_PATH} - -USER $UID - -EXPOSE 8080 - -ENTRYPOINT [ "/docker-entrypoint.sh" ] - -CMD ["nginx", "-g", "daemon off;"] diff --git a/infrastructure/os2display/nginx/docker-entrypoint.sh b/infrastructure/os2display/nginx/docker-entrypoint.sh deleted file mode 100644 index 978fa9f4e..000000000 --- a/infrastructure/os2display/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -set -eux - -## Run templates with configuration. -/usr/local/bin/confd --onetime --backend env --confdir /etc/confd - -entrypoint_log() { - if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "$@" - fi -} - -if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then - if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" - - entrypoint_log "$0: Looking for shell scripts in /docker-entrypoint.d/" - find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.envsh) - if [ -x "$f" ]; then - entrypoint_log "$0: Sourcing $f"; - . "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "$0: Ignoring $f, not executable"; - fi - ;; - *.sh) - if [ -x "$f" ]; then - entrypoint_log "$0: Launching $f"; - "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "$0: Ignoring $f, not executable"; - fi - ;; - *) entrypoint_log "$0: Ignoring $f";; - esac - done - - entrypoint_log "$0: Configuration complete; ready for start up" - else - entrypoint_log "$0: No files found in /docker-entrypoint.d/, skipping configuration" - fi -fi - -exec "$@" diff --git a/infrastructure/os2display/nginx/etc/confd/conf.d/default.conf.toml b/infrastructure/os2display/nginx/etc/confd/conf.d/default.conf.toml deleted file mode 100644 index 185954f0d..000000000 --- a/infrastructure/os2display/nginx/etc/confd/conf.d/default.conf.toml +++ /dev/null @@ -1,7 +0,0 @@ -[template] -src = "default.conf.tmpl" -dest = "/etc/nginx/conf.d/default.conf" -mode = "0644" -keys = [ - "/nginx-config" -] diff --git a/infrastructure/os2display/nginx/etc/confd/conf.d/nginx.conf.toml b/infrastructure/os2display/nginx/etc/confd/conf.d/nginx.conf.toml deleted file mode 100644 index 7c81a661f..000000000 --- a/infrastructure/os2display/nginx/etc/confd/conf.d/nginx.conf.toml +++ /dev/null @@ -1,7 +0,0 @@ -[template] -src = "nginx.conf.tmpl" -dest = "/etc/nginx/nginx.conf" -mode = "0644" -keys = [ - "/nginx-config" -] diff --git a/infrastructure/os2display/nginx/etc/confd/templates/default.conf.tmpl b/infrastructure/os2display/nginx/etc/confd/templates/default.conf.tmpl deleted file mode 100644 index b6f32099b..000000000 --- a/infrastructure/os2display/nginx/etc/confd/templates/default.conf.tmpl +++ /dev/null @@ -1,52 +0,0 @@ -# @see https://symfony.com/doc/current/setup/web_server_configuration.html -server { - listen 8080; - server_name localhost; - root /var/www/html/public; - - location / { - add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; - - # try to serve file directly, fallback to index.php - try_files $uri /index.php$is_args$args; - } - - location = /robots.txt { - add_header Content-Type text/plain; - add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; - return 200 "User-agent: *\nDisallow: /\n"; - } - - location ~ ^/index\.php(/|$) { - fastcgi_pass {{ getenv "PHP_FPM_SERVER" "phpfpm" }}:{{ getenv "PHP_FPM_SERVER_PORT" "9000" }}; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - - internal; - } - - # return 404 for all other php files not matching the front controller - # this prevents access to other php files you don't want to be accessible. - location ~ \.php$ { - return 404; - } - - error_log /var/log/nginx/error.log; - access_log /var/log/nginx/access.log; -} - -server { - listen 8080; - server_name localhost; - root /var/www/html/public; - - error_log off; - access_log off; - - location /stub_status { - stub_status; - } -} diff --git a/infrastructure/os2display/nginx/etc/confd/templates/nginx.conf.tmpl b/infrastructure/os2display/nginx/etc/confd/templates/nginx.conf.tmpl deleted file mode 100644 index 254adf3ec..000000000 --- a/infrastructure/os2display/nginx/etc/confd/templates/nginx.conf.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -worker_processes auto; - -error_log /var/log/nginx/error.log warn; -pid /tmp/nginx.pid; - -events { - worker_connections 2048; - multi_accept on; -} - - -http { - open_file_cache max=10000 inactive=5m; - open_file_cache_valid 5m; - open_file_cache_min_uses 5; - open_file_cache_errors off; - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 15 15; - types_hash_max_size 2048; - - server_tokens off; - - client_max_body_size {{ getenv "NGINX_FPM_UPLOAD_MAX" "8M" }}; - - gzip on; - gzip_disable "msie6"; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_buffers 16 8k; - gzip_http_version 1.0; - gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - set_real_ip_from 172.16.0.0/8; - real_ip_recursive on; - real_ip_header X-Forwarded-For; - - log_format main '$http_x_real_ip - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - error_log /dev/stderr; - access_log /dev/stdout main; - - include /etc/nginx/conf.d/*.conf; -} diff --git a/infrastructure/os2display/run.sh b/infrastructure/os2display/run.sh deleted file mode 100755 index ae23d67b4..000000000 --- a/infrastructure/os2display/run.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -eux - -APP_VERSION=develop - -docker pull nginxinc/nginx-unprivileged:alpine - -docker build --pull --no-cache --build-arg APP_VERSION=${APP_VERSION} --tag=os2display/display-api-service:${APP_VERSION} --file="display-api-service/Dockerfile" display-api-service -docker build --no-cache --build-arg VERSION=${APP_VERSION} --tag=os2display/display-api-service-nginx:${APP_VERSION} --file="nginx/Dockerfile" nginx - -# docker push os2display/display-api-service:${APP_VERSION} -# docker push os2display/display-api-service-nginx:${APP_VERSION} From a4fd679f5ef35525cb9d85891c8a7cf4515c3bf6 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 5 Sep 2025 11:23:16 +0200 Subject: [PATCH 02/38] 5402: Refacktor itk-dev images to single infrastructure. Rename itk-dev images to os2display --- infrastructure/{itkdev => }/Readme.md | 2 +- infrastructure/{itkdev => }/display-api-service/Dockerfile | 2 +- .../{itkdev => }/display-api-service/docker-entrypoint.sh | 0 .../display-api-service/etc/confd/conf.d/env.local.toml | 0 .../display-api-service/etc/confd/templates/env.local.tmpl | 0 infrastructure/{itkdev => }/nginx/Dockerfile | 2 +- infrastructure/{itkdev => }/nginx/docker-entrypoint.sh | 0 .../{itkdev => }/nginx/etc/confd/conf.d/default.conf.toml | 0 .../{itkdev => }/nginx/etc/confd/conf.d/nginx.conf.toml | 0 .../nginx/etc/confd/templates/default.conf.tmpl | 0 .../{itkdev => }/nginx/etc/confd/templates/nginx.conf.tmpl | 0 infrastructure/package-lock.json | 6 ------ infrastructure/{itkdev => }/run.sh | 0 13 files changed, 3 insertions(+), 9 deletions(-) rename infrastructure/{itkdev => }/Readme.md (81%) rename infrastructure/{itkdev => }/display-api-service/Dockerfile (97%) rename infrastructure/{itkdev => }/display-api-service/docker-entrypoint.sh (100%) rename infrastructure/{itkdev => }/display-api-service/etc/confd/conf.d/env.local.toml (100%) rename infrastructure/{itkdev => }/display-api-service/etc/confd/templates/env.local.tmpl (100%) rename infrastructure/{itkdev => }/nginx/Dockerfile (98%) rename infrastructure/{itkdev => }/nginx/docker-entrypoint.sh (100%) rename infrastructure/{itkdev => }/nginx/etc/confd/conf.d/default.conf.toml (100%) rename infrastructure/{itkdev => }/nginx/etc/confd/conf.d/nginx.conf.toml (100%) rename infrastructure/{itkdev => }/nginx/etc/confd/templates/default.conf.tmpl (100%) rename infrastructure/{itkdev => }/nginx/etc/confd/templates/nginx.conf.tmpl (100%) delete mode 100644 infrastructure/package-lock.json rename infrastructure/{itkdev => }/run.sh (100%) diff --git a/infrastructure/itkdev/Readme.md b/infrastructure/Readme.md similarity index 81% rename from infrastructure/itkdev/Readme.md rename to infrastructure/Readme.md index abf2b9d1e..17978bc45 100644 --- a/infrastructure/itkdev/Readme.md +++ b/infrastructure/Readme.md @@ -1,3 +1,3 @@ # ITK-development image build -This folder contains the infrastructure files for building the `itkdev/*` images +This folder contains the infrastructure files for building the `os2display/*` images diff --git a/infrastructure/itkdev/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile similarity index 97% rename from infrastructure/itkdev/display-api-service/Dockerfile rename to infrastructure/display-api-service/Dockerfile index b30ecff1a..5e9c835dd 100644 --- a/infrastructure/itkdev/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,4 +1,4 @@ -FROM itkdev/php8.3-fpm:alpine AS APP_BUILDER +FROM itkdev/php8.4-fpm:alpine AS APP_BUILDER LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" diff --git a/infrastructure/itkdev/display-api-service/docker-entrypoint.sh b/infrastructure/display-api-service/docker-entrypoint.sh similarity index 100% rename from infrastructure/itkdev/display-api-service/docker-entrypoint.sh rename to infrastructure/display-api-service/docker-entrypoint.sh diff --git a/infrastructure/itkdev/display-api-service/etc/confd/conf.d/env.local.toml b/infrastructure/display-api-service/etc/confd/conf.d/env.local.toml similarity index 100% rename from infrastructure/itkdev/display-api-service/etc/confd/conf.d/env.local.toml rename to infrastructure/display-api-service/etc/confd/conf.d/env.local.toml diff --git a/infrastructure/itkdev/display-api-service/etc/confd/templates/env.local.tmpl b/infrastructure/display-api-service/etc/confd/templates/env.local.tmpl similarity index 100% rename from infrastructure/itkdev/display-api-service/etc/confd/templates/env.local.tmpl rename to infrastructure/display-api-service/etc/confd/templates/env.local.tmpl diff --git a/infrastructure/itkdev/nginx/Dockerfile b/infrastructure/nginx/Dockerfile similarity index 98% rename from infrastructure/itkdev/nginx/Dockerfile rename to infrastructure/nginx/Dockerfile index 7a0334dd9..6be4be3c4 100644 --- a/infrastructure/itkdev/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -17,7 +17,7 @@ COPY --from=APPLICATION ${APP_PATH}/public ${APP_PATH}/public WORKDIR ${APP_PATH} # Copy configuration. -COPY etc/ /etc/ +COPY etc /etc/ # Install configuration template handler ADD https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 /usr/local/bin/confd diff --git a/infrastructure/itkdev/nginx/docker-entrypoint.sh b/infrastructure/nginx/docker-entrypoint.sh similarity index 100% rename from infrastructure/itkdev/nginx/docker-entrypoint.sh rename to infrastructure/nginx/docker-entrypoint.sh diff --git a/infrastructure/itkdev/nginx/etc/confd/conf.d/default.conf.toml b/infrastructure/nginx/etc/confd/conf.d/default.conf.toml similarity index 100% rename from infrastructure/itkdev/nginx/etc/confd/conf.d/default.conf.toml rename to infrastructure/nginx/etc/confd/conf.d/default.conf.toml diff --git a/infrastructure/itkdev/nginx/etc/confd/conf.d/nginx.conf.toml b/infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml similarity index 100% rename from infrastructure/itkdev/nginx/etc/confd/conf.d/nginx.conf.toml rename to infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml diff --git a/infrastructure/itkdev/nginx/etc/confd/templates/default.conf.tmpl b/infrastructure/nginx/etc/confd/templates/default.conf.tmpl similarity index 100% rename from infrastructure/itkdev/nginx/etc/confd/templates/default.conf.tmpl rename to infrastructure/nginx/etc/confd/templates/default.conf.tmpl diff --git a/infrastructure/itkdev/nginx/etc/confd/templates/nginx.conf.tmpl b/infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl similarity index 100% rename from infrastructure/itkdev/nginx/etc/confd/templates/nginx.conf.tmpl rename to infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl diff --git a/infrastructure/package-lock.json b/infrastructure/package-lock.json deleted file mode 100644 index 4ca926f5d..000000000 --- a/infrastructure/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "app", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/infrastructure/itkdev/run.sh b/infrastructure/run.sh similarity index 100% rename from infrastructure/itkdev/run.sh rename to infrastructure/run.sh From 6901548d6b0d8a54b5a0471c3f6028fe8c9e6ec2 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Fri, 5 Sep 2025 11:24:39 +0200 Subject: [PATCH 03/38] 5402: Update github action image uild jobs for new infrastructure --- ...l => docker_build_images_from_develop.yml} | 18 +++--- ...g.yml => docker_build_images_from_tag.yml} | 18 +++--- .../os2display_docker_build_develop.yml | 60 ------------------ .../workflows/os2display_docker_build_tag.yml | 63 ------------------- 4 files changed, 18 insertions(+), 141 deletions(-) rename .github/workflows/{itkdev_docker_build_develop.yml => docker_build_images_from_develop.yml} (71%) rename .github/workflows/{itkdev_docker_build_tag.yml => docker_build_images_from_tag.yml} (73%) delete mode 100644 .github/workflows/os2display_docker_build_develop.yml delete mode 100644 .github/workflows/os2display_docker_build_tag.yml diff --git a/.github/workflows/itkdev_docker_build_develop.yml b/.github/workflows/docker_build_images_from_develop.yml similarity index 71% rename from .github/workflows/itkdev_docker_build_develop.yml rename to .github/workflows/docker_build_images_from_develop.yml index aaef33621..bcf6cd50f 100644 --- a/.github/workflows/itkdev_docker_build_develop.yml +++ b/.github/workflows/docker_build_images_from_develop.yml @@ -4,8 +4,8 @@ on: branches: - "develop" -# This Action builds to itkdev/* using ./infrastructure/itkdev/* -name: ITK Dev - Build docker image (develop) +# This Action builds to os2display/* using ./infrastructure/* +name: Build docker image (develop) jobs: docker: @@ -15,7 +15,7 @@ jobs: COMPOSER_ALLOW_SUPERUSER: 1 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Login to DockerHub uses: docker/login-action@v3 @@ -28,13 +28,13 @@ jobs: id: meta-api uses: docker/metadata-action@v5 with: - images: itkdev/os2display-api-service + images: os2display/os2display-api-service - name: Build and push (API) uses: docker/build-push-action@v5 with: - context: ./infrastructure/itkdev/display-api-service/ - file: ./infrastructure/itkdev/display-api-service/Dockerfile + context: ./infrastructure/display-api-service/ + file: ./infrastructure/display-api-service/Dockerfile build-args: | VERSION=${{ env.APP_VERSION }} push: true @@ -46,13 +46,13 @@ jobs: id: meta-nginx uses: docker/metadata-action@v5 with: - images: itkdev/os2display-api-service-nginx + images: os2display/os2display-api-service-nginx - name: Build and push (Nginx) uses: docker/build-push-action@v5 with: - context: ./infrastructure/itkdev/nginx/ - file: ./infrastructure/itkdev/nginx/Dockerfile + context: ./infrastructure/nginx/ + file: ./infrastructure/nginx/Dockerfile build-args: | APP_VERSION=${{ env.APP_VERSION }} push: true diff --git a/.github/workflows/itkdev_docker_build_tag.yml b/.github/workflows/docker_build_images_from_tag.yml similarity index 73% rename from .github/workflows/itkdev_docker_build_tag.yml rename to .github/workflows/docker_build_images_from_tag.yml index f64644a28..208a41b61 100644 --- a/.github/workflows/itkdev_docker_build_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -4,8 +4,8 @@ on: tags: - "*" -# This Action builds to itkdev/* using ./infrastructure/itkdev/* -name: ITK Dev - Build docker image (tag) +# This Action builds to os2display/* using ./infrastructure/* +name: Build docker image (tag) jobs: docker: @@ -14,7 +14,7 @@ jobs: COMPOSER_ALLOW_SUPERUSER: 1 steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Login to DockerHub uses: docker/login-action@v3 @@ -27,13 +27,13 @@ jobs: id: meta-api uses: docker/metadata-action@v5 with: - images: itkdev/os2display-api-service + images: os2display/os2display-api-service - name: Build and push (API) uses: docker/build-push-action@v5 with: - context: ./infrastructure/itkdev/display-api-service/ - file: ./infrastructure/itkdev/display-api-service/Dockerfile + context: ./infrastructure/display-api-service/ + file: ./infrastructure/display-api-service/Dockerfile build-args: | APP_VERSION=${{ github.ref }} push: true @@ -45,7 +45,7 @@ jobs: id: meta-nginx uses: docker/metadata-action@v5 with: - images: itkdev/os2display-api-service-nginx + images: os2display/os2display-api-service-nginx - name: Get the tag id: get_tag @@ -54,8 +54,8 @@ jobs: - name: Build and push (Nginx) uses: docker/build-push-action@v5 with: - context: ./infrastructure/itkdev/nginx/ - file: ./infrastructure/itkdev/nginx/Dockerfile + context: ./infrastructure/nginx/ + file: ./infrastructure/nginx/Dockerfile build-args: | APP_VERSION=${{ steps.get_tag.outputs.git_tag }} push: true diff --git a/.github/workflows/os2display_docker_build_develop.yml b/.github/workflows/os2display_docker_build_develop.yml deleted file mode 100644 index bcdf09a6c..000000000 --- a/.github/workflows/os2display_docker_build_develop.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- -on: - push: - branches: - - "develop" - -# This Action builds to os2display/* using ./infrastructure/os2display/* -name: OS2display - Build docker image (develop) - -jobs: - docker: - runs-on: ubuntu-latest - env: - APP_VERSION: develop - COMPOSER_ALLOW_SUPERUSER: 1 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # Build api - - name: Docker meta (API) - id: meta-api - uses: docker/metadata-action@v5 - with: - images: os2display/display-api-service - - - name: Build and push (API) - uses: docker/build-push-action@v5 - with: - context: ./infrastructure/os2display/display-api-service/ - file: ./infrastructure/os2display/display-api-service/Dockerfile - build-args: | - VERSION=${{ env.APP_VERSION }} - push: true - tags: ${{ steps.meta-api.outputs.tags }} - labels: ${{ steps.meta-api.outputs.labels }} - - # Build nginx (depends on api build) - - name: Docker meta (Nginx) - id: meta-nginx - uses: docker/metadata-action@v5 - with: - images: os2display/display-api-service-nginx - - - name: Build and push (Nginx) - uses: docker/build-push-action@v5 - with: - context: ./infrastructure/os2display/nginx/ - file: ./infrastructure/os2display/nginx/Dockerfile - build-args: | - APP_VERSION=${{ env.APP_VERSION }} - push: true - tags: ${{ steps.meta-nginx.outputs.tags }} - labels: ${{ steps.meta-nginx.outputs.labels }} diff --git a/.github/workflows/os2display_docker_build_tag.yml b/.github/workflows/os2display_docker_build_tag.yml deleted file mode 100644 index 8bd2b12aa..000000000 --- a/.github/workflows/os2display_docker_build_tag.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- -on: - push: - tags: - - "*" - -# This Action builds to os2display/* using ./infrastructure/os2display/* -name: OS2display - Build docker image (tag) - -jobs: - docker: - runs-on: ubuntu-latest - env: - COMPOSER_ALLOW_SUPERUSER: 1 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # Build api - - name: Docker meta (API) - id: meta-api - uses: docker/metadata-action@v5 - with: - images: os2display/display-api-service - - - name: Build and push (API) - uses: docker/build-push-action@v5 - with: - context: ./infrastructure/os2display/display-api-service/ - file: ./infrastructure/os2display/display-api-service/Dockerfile - build-args: | - APP_VERSION=${{ github.ref }} - push: true - tags: ${{ steps.meta-api.outputs.tags }} - labels: ${{ steps.meta-api.outputs.labels }} - - # Build nginx (depends on api build) - - name: Docker meta (Nginx) - id: meta-nginx - uses: docker/metadata-action@v5 - with: - images: os2display/display-api-service-nginx - - - name: Get the tag - id: get_tag - run: echo ::set-output name=git_tag::$(echo $GITHUB_REF_NAME) - - - name: Build and push (Nginx) - uses: docker/build-push-action@v5 - with: - context: ./infrastructure/os2display/nginx/ - file: ./infrastructure/os2display/nginx/Dockerfile - build-args: | - APP_VERSION=${{ steps.get_tag.outputs.git_tag }} - push: true - tags: ${{ steps.meta-nginx.outputs.tags }} - labels: ${{ steps.meta-nginx.outputs.labels }} From 2b84d3255b150d87f87b7bee7d58435bd178c36c Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 3 Nov 2025 13:03:56 +0100 Subject: [PATCH 04/38] 5402: Update infrastructure for 3.0 --- .dockerignore | 68 ++++++++++++++++++ .github/Taskfile.yml | 46 ++++++++++++ .../docker_build_images_from_develop.yml | 23 ++++-- .../docker_build_images_from_tag.yml | 21 +++--- .github/workflows/github_build_release.yml | 20 +++--- .gitignore | 2 - docker-compose.server.yml | 2 +- docker-compose.yml | 2 +- infrastructure/build-n-push.sh | 27 +++++++ infrastructure/display-api-service/Dockerfile | 59 ++++++++------- .../display-api-service/docker-entrypoint.sh | 6 +- .../etc/confd/conf.d/env.local.toml | 8 --- .../etc/confd/templates/env.local.tmpl | 71 ------------------- infrastructure/nginx/Dockerfile | 45 +++++++++--- .../etc/confd/templates/default.conf.tmpl | 23 ++++++ infrastructure/run.sh | 13 ---- 16 files changed, 273 insertions(+), 163 deletions(-) create mode 100644 .dockerignore create mode 100644 .github/Taskfile.yml create mode 100755 infrastructure/build-n-push.sh delete mode 100644 infrastructure/display-api-service/etc/confd/conf.d/env.local.toml delete mode 100644 infrastructure/display-api-service/etc/confd/templates/env.local.tmpl delete mode 100755 infrastructure/run.sh diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..7e18bc03c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,68 @@ +/.git +!/.git/config + +# Unneeded application files +/.docker/data/README.md +/.github +/docs +/fixtures +/infrastructure +/public/build +/public/fixtures +public/build +public/fixtures +public/media/* +!public/media/thumbnail_other.png +!public/media/thumbnail_video.png +/scripts +/tests + +###> symfony/framework-bundle ### +/.env.local +/.env.local.php +/.env.*.local +/config/secrets/prod/prod.decrypt.private.php +/var/ +/vendor/ +###< symfony/framework-bundle ### + +###> friendsofphp/php-cs-fixer ### +/.php-cs-fixer.php +/.php-cs-fixer.cache +###< friendsofphp/php-cs-fixer ### + +###> phpunit/phpunit ### +/phpunit.xml +.phpunit.result.cache +###< phpunit/phpunit ### + +###> lexik/jwt-authentication-bundle ### +/config/jwt/*.pem +###< lexik/jwt-authentication-bundle ### + +xdebug.ini +launch.json + +###> liip/imagine-bundle ### +/public/media/cache/ +###< liip/imagine-bundle ### + +###> phpstan/phpstan ### +phpstan.neon +###< phpstan/phpstan ### + +###> pentatrion/vite-bundle ### +/node_modules/ +/public/build/ +###< pentatrion/vite-bundle ### + +#> Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +#< Playwright + +###> vincentlanglet/twig-cs-fixer ### +/.twig-cs-fixer.cache +###< vincentlanglet/twig-cs-fixer ### diff --git a/.github/Taskfile.yml b/.github/Taskfile.yml new file mode 100644 index 000000000..2cb169d48 --- /dev/null +++ b/.github/Taskfile.yml @@ -0,0 +1,46 @@ +# Task file for GitHub Actions, https://taskfile.dev/ + +version: "3" + +# https://taskfile.dev/usage/#env-files +dotenv: [".env.local", ".env"] + +tasks: + default: + desc: "List all tasks" + cmds: + - task --list-all + silent: true + + build-prod: + desc: "Build application for production" + cmds: + - task setup-network + - task composer-install + - task npm-install + - task install-cleanup + + setup-network: + desc: "Setup docker frontend network" + cmds: + - docker network create frontend + + composer-install: + desc: "Install dependencies with composer." + cmds: + - docker compose run --rm --env APP_ENV=prod phpfpm composer install --no-dev -o --classmap-authoritative + - docker compose run --rm --env APP_ENV=prod phpfpm composer clear-cache + + npm-install: + desc: "Installs node dependencies with npm." + cmds: + - docker compose run --rm node npm install + - docker compose run --rm node npm run build + + install-cleanup: + desc: "Cleanup after install" + cmds: + - rm -rf infrastructure + - rm -rf fixtures + - rm -rf tests + - rm -rf node_modules diff --git a/.github/workflows/docker_build_images_from_develop.yml b/.github/workflows/docker_build_images_from_develop.yml index bcf6cd50f..0becba3b0 100644 --- a/.github/workflows/docker_build_images_from_develop.yml +++ b/.github/workflows/docker_build_images_from_develop.yml @@ -14,24 +14,27 @@ jobs: APP_VERSION: develop COMPOSER_ALLOW_SUPERUSER: 1 steps: - - name: Checkout - uses: actions/checkout@v5 - - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USER }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + # Build api - name: Docker meta (API) id: meta-api uses: docker/metadata-action@v5 with: - images: os2display/os2display-api-service + images: os2display/display-api-service - name: Build and push (API) - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ./infrastructure/display-api-service/ file: ./infrastructure/display-api-service/Dockerfile @@ -40,16 +43,19 @@ jobs: push: true tags: ${{ steps.meta-api.outputs.tags }} labels: ${{ steps.meta-api.outputs.labels }} + provenance: mode=max + sbom: true + platforms: linux/amd64,linux/arm64 # Build nginx (depends on api build) - name: Docker meta (Nginx) id: meta-nginx uses: docker/metadata-action@v5 with: - images: os2display/os2display-api-service-nginx + images: os2display/display-api-service-nginx - name: Build and push (Nginx) - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ./infrastructure/nginx/ file: ./infrastructure/nginx/Dockerfile @@ -58,3 +64,6 @@ jobs: push: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} + provenance: mode=max + sbom: true + platforms: linux/amd64,linux/arm64 diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index 208a41b61..4b441be89 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -10,27 +10,28 @@ name: Build docker image (tag) jobs: docker: runs-on: ubuntu-latest - env: - COMPOSER_ALLOW_SUPERUSER: 1 steps: - - name: Checkout - uses: actions/checkout@v5 - - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USER }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + # Build api - name: Docker meta (API) id: meta-api uses: docker/metadata-action@v5 with: - images: os2display/os2display-api-service + images: os2display/display-api-service - name: Build and push (API) - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: ./infrastructure/display-api-service/ file: ./infrastructure/display-api-service/Dockerfile @@ -39,13 +40,15 @@ jobs: push: true tags: ${{ steps.meta-api.outputs.tags }} labels: ${{ steps.meta-api.outputs.labels }} + provenance: mode=max + sbom: true # Build nginx (depends on api build) - name: Docker meta (Nginx) id: meta-nginx uses: docker/metadata-action@v5 with: - images: os2display/os2display-api-service-nginx + images: os2display/display-api-service-nginx - name: Get the tag id: get_tag @@ -61,3 +64,5 @@ jobs: push: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} + provenance: mode=max + sbom: true diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 2ca6b44d7..810ab96e3 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -8,23 +8,23 @@ name: Create Github Release permissions: contents: write +env: + COMPOSE_USER: runner + jobs: create-release: runs-on: ubuntu-latest - env: - COMPOSER_ALLOW_SUPERUSER: 1 - APP_ENV: prod steps: - name: Checkout uses: actions/checkout@v4 - - name: Composer install - run: | - docker network create frontend - docker compose run --rm --user=root --env APP_ENV=prod phpfpm composer install --no-dev -o --classmap-authoritative - docker compose run --rm --user=root --env APP_ENV=prod phpfpm composer clear-cache - rm -rf infrastructure + - name: Install Task task runner + uses: go-task/setup-task@v1 + - name: Install, Build, Cleanup + run: | + task --taskfile=.github/Taskfile.yaml build-prod + - name: Make assets dir run: | mkdir -p ../assets @@ -39,7 +39,7 @@ jobs: - name: Create a release in GitHub and uploads assets run: | - gh release create ${{ github.ref_name }} --verify-tag --generate-notes ../assets/*.* + gh release create ${{ github.ref_name }} --verify-tag --generate-notes ${{ steps.prerelease.outputs.flag }} ../assets/*.* env: GITHUB_TOKEN: ${{ github.TOKEN }} shell: bash diff --git a/.gitignore b/.gitignore index 6a75d6466..521b8cb58 100644 --- a/.gitignore +++ b/.gitignore @@ -25,8 +25,6 @@ /.php-cs-fixer.cache ###< friendsofphp/php-cs-fixer ### -node_modules - public/media/* !public/media/thumbnail_video.png !public/media/thumbnail_other.png diff --git a/docker-compose.server.yml b/docker-compose.server.yml index 614d67b10..bc011cac0 100644 --- a/docker-compose.server.yml +++ b/docker-compose.server.yml @@ -8,7 +8,7 @@ networks: services: phpfpm: - image: itkdev/php8.3-fpm:alpine + image: itkdev/php8.4-fpm:alpine restart: unless-stopped networks: - app diff --git a/docker-compose.yml b/docker-compose.yml index b5c08946d..b18ab3814 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,7 +27,7 @@ services: #- ENCRYPT=1 # Uncomment to enable database encryption. phpfpm: - image: itkdev/php8.3-fpm:latest + image: itkdev/php8.4-fpm:latest user: ${COMPOSE_USER:-deploy} networks: - app diff --git a/infrastructure/build-n-push.sh b/infrastructure/build-n-push.sh new file mode 100755 index 000000000..04f244043 --- /dev/null +++ b/infrastructure/build-n-push.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +set -eux + +APP_VERSION=develop + +docker pull itkdev/php8.4-fpm:alpine +docker pull nginxinc/nginx-unprivileged:alpine + +docker build --build-context repository-root=.. \ + --platform linux/amd64,linux/arm64 \ + --pull \ + --no-cache \ + --build-arg APP_VERSION=${APP_VERSION} \ + --tag=turegjorup/display-api-service:${APP_VERSION} \ + --file="display-api-service/Dockerfile" display-api-service + + +docker build --build-context repository-root=.. \ + --platform linux/amd64,linux/arm64 \ + --no-cache \ + --build-arg VERSION=${APP_VERSION} \ + --tag=turegjorup/display-api-service-nginx:${APP_VERSION} \ + --file="nginx/Dockerfile" nginx + +docker push os2display/display-api-service:${APP_VERSION} +docker push os2display/display-api-service-nginx:${APP_VERSION} diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 5e9c835dd..f50de55ff 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,33 +1,43 @@ -FROM itkdev/php8.4-fpm:alpine AS APP_BUILDER +######### API backend ######## +FROM itkdev/php8.4-fpm:alpine AS api_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" -ENV APP_PATH=/var/www/html +ENV APP_API_PATH=/var/www/html USER root -# Move site into the container. -ADD https://github.com/os2display/display-api-service/archive/${APP_VERSION}.tar.gz /tmp/app.tar -RUN tar -zxf /tmp/app.tar --strip-components=1 -C ${APP_PATH} \ - && rm /tmp/app.tar - # Add composer in from the official composer image (also alpine). COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer -WORKDIR ${APP_PATH} +WORKDIR ${APP_API_PATH} + +USER deploy + +# Copy only composer files first for better layer caching +COPY --chown=deploy:deploy --from=repository-root composer.json composer.lock symfony.lock ${APP_API_PATH}/ + +# Install composer packages first (better image layer caching) +RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts + +# Copy application source (needed for build step) +COPY --chown=deploy:deploy --from=repository-root ./ ${APP_API_PATH}/ + +# Remove frontend apps from api build +RUN rm -rf /assets -## Install assets, which requires a HACK as redis is not available (should be removed later on). -RUN COMPOSER_ALLOW_SUPERUSER=1 APP_ENV=prod composer install --no-dev -o --classmap-authoritative +# Install composer packages, which requires a HACK as redis is not available (should be removed later on). +RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative -RUN rm -rf infrastructure #### ## Build main application image. #### -FROM itkdev/php8.3-fpm:alpine + +FROM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " -ENV APP_PATH=/var/www/html \ +ENV APP_API_PATH=/var/www/html \ COMPOSER_VERSION=2 USER root @@ -35,29 +45,18 @@ USER root # Add composer needed to run optimizations after config is loaded. COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer -# Install the application. -COPY --from=APP_BUILDER ${APP_PATH} ${APP_PATH} -RUN mkdir -p ${APP_PATH}/config/secrets \ - && chown -R deploy:deploy ${APP_PATH} - # Download Prometheus php-fpm export. -COPY --from=hipages/php-fpm_exporter:1.1.1 /php-fpm_exporter /usr/local/bin/php-fpm_exporter - -# Copy configuration. -COPY etc /etc/ - -# Install configuration template handler -ADD https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 /usr/local/bin/confd -RUN chmod +x /usr/local/bin/confd - -# Copy confd onfiguration. -COPY etc /etc/ +COPY --from=hipages/php-fpm_exporter:2.2.0 /php-fpm_exporter /usr/local/bin/php-fpm_exporter COPY docker-entrypoint.sh /usr/local/bin/ RUN chmod +x /usr/local/bin/docker-entrypoint.sh USER deploy -WORKDIR ${APP_PATH} +# Install the api application. +COPY --chown=deploy:deploy --from=api_app_builder ${APP_API_PATH} ${APP_API_PATH} +RUN mkdir -p ${APP_API_PATH}/config/secrets + +WORKDIR ${APP_API_PATH} CMD [ "docker-entrypoint.sh" ] diff --git a/infrastructure/display-api-service/docker-entrypoint.sh b/infrastructure/display-api-service/docker-entrypoint.sh index 306e9f13d..744897e8b 100644 --- a/infrastructure/display-api-service/docker-entrypoint.sh +++ b/infrastructure/display-api-service/docker-entrypoint.sh @@ -2,10 +2,8 @@ set -eux -## Run templates with configuration. -/usr/local/bin/confd --onetime --backend env --confdir /etc/confd - -## Bump env.local into PHP for better performance. +## Dump dotenv files into PHP for better performance. +## @see https://symfony.com/doc/6.4/configuration.html#configuring-environment-variables-in-production composer dump-env prod ## Warm-up Symfony cache (with the current configuration). diff --git a/infrastructure/display-api-service/etc/confd/conf.d/env.local.toml b/infrastructure/display-api-service/etc/confd/conf.d/env.local.toml deleted file mode 100644 index d614cc69a..000000000 --- a/infrastructure/display-api-service/etc/confd/conf.d/env.local.toml +++ /dev/null @@ -1,8 +0,0 @@ -[template] -src = "env.local.tmpl" -dest = "/var/www/html/.env.local" -owner = "deploy" -mode = "0644" -keys = [ - "/app-config" -] diff --git a/infrastructure/display-api-service/etc/confd/templates/env.local.tmpl b/infrastructure/display-api-service/etc/confd/templates/env.local.tmpl deleted file mode 100644 index 76e585b97..000000000 --- a/infrastructure/display-api-service/etc/confd/templates/env.local.tmpl +++ /dev/null @@ -1,71 +0,0 @@ -###> symfony/framework-bundle ### -APP_ENV={{ getenv "APP_ENV" "prod" }} -APP_SECRET={{ getenv "APP_SECRET" "MySuperSecret" }} -TRUSTED_PROXIES={{ getenv "APP_TRUSTED_PROXIES" "127.0.0.1,REMOTE_ADDR" }} -###< symfony/framework-bundle ### - -###> doctrine/doctrine-bundle ### -DATABASE_URL={{ getenv "APP_DATABASE_URL" "mysql://db:db@mariadb:3306/db?serverVersion=mariadb-10.4.0" }} -###< doctrine/doctrine-bundle ### - -###> nelmio/cors-bundle ### -CORS_ALLOW_ORIGIN={{ getenv "APP_CORS_ALLOW_ORIGIN" "'^https?://localhost(:[0-9]+)?$'" }} -###< nelmio/cors-bundle ### - -###> App ### -APP_DEFAULT_DATE_FORMAT='{{ getenv "APP_DEFAULT_DATE_FORMAT" "Y-m-d\\TH:i:s\\Z" }}' -APP_ACTIVATION_CODE_EXPIRE_INTERVAL='{{ getenv "APP_ACTIVATION_CODE_EXPIRE_INTERVAL" "P2D" }}' -###< App ### - -###> lexik/jwt-authentication-bundle ### -JWT_PASSPHRASE={{ getenv "APP_JWT_PASSPHRASE" }} -JWT_TOKEN_TTL={{ getenv "APP_JWT_TOKEN_TTL" "3600" }} -JWT_SCREEN_TOKEN_TTL={{ getenv "APP_JWT_SCREEN_TOKEN_TTL" "3600" }} -###< lexik/jwt-authentication-bundle ### - -###> gesdinet/jwt-refresh-token-bundle ### -JWT_REFRESH_TOKEN_TTL={{ getenv "APP_JWT_REFRESH_TOKEN_TTL" "2592000" }} -JWT_SCREEN_REFRESH_TOKEN_TTL={{ getenv "APP_JWT_SCREEN_REFRESH_TOKEN_TTL" "2592000" }} -###< gesdinet/jwt-refresh-token-bundle ### - -###> itk-dev/openid-connect-bundle ### -# internal provider -INTERNAL_OIDC_METADATA_URL={{ getenv "APP_INTERNAL_OIDC_METADATA_URL" "" }} -INTERNAL_OIDC_CLIENT_ID={{ getenv "APP_INTERNAL_OIDC_CLIENT_ID" "" }} -INTERNAL_OIDC_CLIENT_SECRET={{ getenv "APP_INTERNAL_OIDC_CLIENT_SECRET" "" }} -INTERNAL_OIDC_REDIRECT_URI={{ getenv "APP_INTERNAL_OIDC_REDIRECT_URI" "" }} -INTERNAL_OIDC_LEEWAY={{ getenv "APP_INTERNAL_OIDC_LEEWAY" "30" }} - -# external provider -EXTERNAL_OIDC_METADATA_URL={{ getenv "APP_EXTERNAL_OIDC_METADATA_URL" "" }} -EXTERNAL_OIDC_CLIENT_ID={{ getenv "APP_EXTERNAL_OIDC_CLIENT_ID" "" }} -EXTERNAL_OIDC_CLIENT_SECRET={{ getenv "APP_EXTERNAL_OIDC_CLIENT_SECRET" "" }} -EXTERNAL_OIDC_REDIRECT_URI={{ getenv "APP_EXTERNAL_OIDC_REDIRECT_URI" "" }} -EXTERNAL_OIDC_LEEWAY={{ getenv "APP_EXTERNAL_OIDC_LEEWAY" "30" }} -EXTERNAL_OIDC_HASH_SALT={{ getenv "APP_EXTERNAL_OIDC_HASH_SALT" "" }} - -CLI_REDIRECT={{ getenv "APP_CLI_REDIRECT" "" }} -###< itk-dev/openid-connect-bundle ### - -###> redis ### -REDIS_CACHE_PREFIX={{ getenv "APP_CLI_REDIRECT" "DisplayApiService" }} -REDIS_CACHE_DSN={{ getenv "APP_CLI_REDIRECT" "redis://redis:6379/0" }} -###< redis ### - -###> Calendar Api Feed Source ### -CALENDAR_API_FEED_SOURCE_LOCATION_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_LOCATION_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_RESOURCE_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_RESOURCE_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_EVENT_ENDPOINT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_EVENT_ENDPOINT" "" }} -CALENDAR_API_FEED_SOURCE_CUSTOM_MAPPINGS={{ getenv "APP_CALENDAR_API_FEED_SOURCE_CUSTOM_MAPPINGS" "'{}'" }} -CALENDAR_API_FEED_SOURCE_EVENT_MODIFIERS={{ getenv "APP_CALENDAR_API_FEED_SOURCE_EVENT_MODIFIERS" "'{}'" }} -CALENDAR_API_FEED_SOURCE_DATE_FORMAT={{ getenv "APP_CALENDAR_API_FEED_SOURCE_DATE_FORMAT" "" }} -CALENDAR_API_FEED_SOURCE_DATE_TIMEZONE={{ getenv "APP_CALENDAR_API_FEED_SOURCE_DATE_TIMEZONE" "" }} -CALENDAR_API_FEED_SOURCE_CACHE_EXPIRE_SECONDS={{ getenv "APP_CALENDAR_API_FEED_SOURCE_CACHE_EXPIRE_SECONDS" "300" }} -###< Calendar Api Feed Source ### - -EVENTDATABASE_API_V2_CACHE_EXPIRE_SECONDS={{ getenv "APP_EVENTDATABASE_API_V2_CACHE_EXPIRE_SECONDS" "300" }} - -TRACK_SCREEN_INFO={{ getenv "APP_TRACK_SCREEN_INFO" "false" }} -TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS={{ getenv "APP_TRACK_SCREEN_INFO_UPDATE_INTERVAL_SECONDS" "300" }} - -APP_KEY_VAULT_JSON={{ getenv "APP_KEY_VAULT_JSON" "{}" }} diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 6be4be3c4..6754aba58 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,20 +1,49 @@ +######## Client [Screen|Admin] build ######## +FROM node:24-alpine AS client_app_builder +LABEL maintainer="ITK Dev " + ARG APP_VERSION="develop" -FROM itkdev/os2display-api-service:${APP_VERSION} as APPLICATION +ARG APP_RELEASE_VERSION="develop" +ARG APP_RELEASE_TIMESTAMP=0 +ENV APP_CLIENT_PATH=/app + +WORKDIR ${APP_CLIENT_PATH} + +# Copy only necessary files for npm install +COPY --from=repository-root package.json package-lock.json vite.config.js ${APP_CLIENT_PATH}/ + +# Install dependencies +RUN npm ci --no-audit --no-fund +# Copy source files needed for build +COPY --from=repository-root assets/ ${APP_CLIENT_PATH}/assets/ +COPY --from=repository-root public/client/ ${APP_CLIENT_PATH}/public/client/ +COPY --from=repository-root vite.config.js ${APP_CLIENT_PATH}/ + +# Build the application +RUN npm run build + +# Clean up build dependencies and cache +RUN npm cache clean --force && \ + rm -rf node_modules/.cache && \ + rm -rf /root/.npm + + +######## Nginx build ######## FROM nginxinc/nginx-unprivileged:alpine LABEL maintainer="ITK Dev " ARG UID=101 ARG GID=101 -ENV APP_PATH=/var/www/html +ENV APP_CLIENT_PATH=/app +ENV APP_API_PATH=/var/www/html USER root -RUN mkdir -p ${APP_PATH}/public - -COPY --from=APPLICATION ${APP_PATH}/public ${APP_PATH}/public +RUN mkdir -p ${APP_API_PATH}/public +COPY --from=client_app_builder ${APP_CLIENT_PATH}/public ${APP_API_PATH}/public -WORKDIR ${APP_PATH} +WORKDIR ${APP_API_PATH} # Copy configuration. COPY etc /etc/ @@ -25,8 +54,8 @@ RUN chmod +x /usr/local/bin/confd COPY docker-entrypoint.sh / RUN chmod +x /docker-entrypoint.sh \ - && chown -R $UID:0 ${APP_PATH} \ - && chmod -R g+w ${APP_PATH} + && chown -R $UID:0 ${APP_API_PATH} \ + && chmod -R g+w ${APP_API_PATH} USER $UID diff --git a/infrastructure/nginx/etc/confd/templates/default.conf.tmpl b/infrastructure/nginx/etc/confd/templates/default.conf.tmpl index b6f32099b..7fcd10283 100644 --- a/infrastructure/nginx/etc/confd/templates/default.conf.tmpl +++ b/infrastructure/nginx/etc/confd/templates/default.conf.tmpl @@ -11,6 +11,29 @@ server { try_files $uri /index.php$is_args$args; } + # Cache static assets built by Vite under /public/build + location /build/ { + access_log off; + log_not_found off; + + # Serve files directly + try_files $uri =404; + + # Long-term caching for fingerprinted assets + add_header Cache-Control "public, max-age=31536000, immutable"; + expires 1y; + + # Also allow CORS for fonts and similar assets if needed + add_header Access-Control-Allow-Origin "*" always; + + # Do not set X-Robots-Tag for assets + } + + # Screen client online check should just serve static files + location /client/online-check { + index index.html index.htm; + } + location = /robots.txt { add_header Content-Type text/plain; add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; diff --git a/infrastructure/run.sh b/infrastructure/run.sh deleted file mode 100755 index b028f5cdc..000000000 --- a/infrastructure/run.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -eux - -APP_VERSION=develop - -docker pull nginxinc/nginx-unprivileged:alpine - -docker build --pull --no-cache --build-arg APP_VERSION=${APP_VERSION} --tag=itkdev/os2display-api-service:${APP_VERSION} --file="display-api-service/Dockerfile" display-api-service -docker build --no-cache --build-arg VERSION=${APP_VERSION} --tag=itkdev/os2display-api-service-nginx:${APP_VERSION} --file="nginx/Dockerfile" nginx - -# docker push itkdev/os2display-api-service:${APP_VERSION} -# docker push itkdev/os2display-api-service-nginx:${APP_VERSION} From 7628dc0925b6534f315ea743e99dd2458f76945e Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 8 Dec 2025 08:47:11 +0100 Subject: [PATCH 05/38] 5402: Fix Vite missing prod caching config --- config/packages/pentatrion_vite.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 config/packages/pentatrion_vite.yaml diff --git a/config/packages/pentatrion_vite.yaml b/config/packages/pentatrion_vite.yaml new file mode 100644 index 000000000..c8b11e194 --- /dev/null +++ b/config/packages/pentatrion_vite.yaml @@ -0,0 +1,4 @@ +# @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 +when@prod: + pentatrion_vite: + cache: true From acc6ea89feeae8ac0f91203ad7a17677aeace3f1 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 8 Dec 2025 08:48:17 +0100 Subject: [PATCH 06/38] 5402: Update Psalm to enable PHP 8.4 image builds --- composer.json | 2 +- composer.lock | 3591 +++++++++++++++++++++++++++++++-------------- package-lock.json | 24 +- 3 files changed, 2478 insertions(+), 1139 deletions(-) diff --git a/composer.json b/composer.json index 3108dd75c..30132d0cb 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,7 @@ "symfony/stopwatch": "~6.4.0", "symfony/var-dumper": "~6.4.0", "symfony/web-profiler-bundle": "~6.4.0", - "vimeo/psalm": "^5.12.0", + "vimeo/psalm": "^6.13.0", "vincentlanglet/twig-cs-fixer": "^3.8", "weirdan/doctrine-psalm-plugin": "^2.0" }, diff --git a/composer.lock b/composer.lock index edaae5488..37f155558 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1bd6fd456477d1e03a03bb4359ad3e77", + "content-hash": "567a746ddcb5a440c396fc6ea9cfa7ac", "packages": [ { "name": "api-platform/core", @@ -445,16 +445,16 @@ }, { "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,20 +750,21 @@ "type": "tidelift" } ], + "abandoned": true, "time": "2022-05-20T20:07:39+00:00" }, { "name": "doctrine/collections", - "version": "2.3.0", + "version": "2.4.0", "source": { "type": "git", "url": "https://github.com/doctrine/collections.git", - "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d" + "reference": "9acfeea2e8666536edff3d77c531261c63680160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/2eb07e5953eed811ce1b309a7478a3b236f2273d", - "reference": "2eb07e5953eed811ce1b309a7478a3b236f2273d", + "url": "https://api.github.com/repos/doctrine/collections/zipball/9acfeea2e8666536edff3d77c531261c63680160", + "reference": "9acfeea2e8666536edff3d77c531261c63680160", "shasum": "" }, "require": { @@ -775,11 +773,11 @@ "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" + "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.3.0" + "source": "https://github.com/doctrine/collections/tree/2.4.0" }, "funding": [ { @@ -839,7 +837,7 @@ "type": "tidelift" } ], - "time": "2025-03-22T10:17:19+00:00" + "time": "2025-10-25T09:18:13+00:00" }, { "name": "doctrine/common", @@ -934,36 +932,39 @@ }, { "name": "doctrine/dbal", - "version": "3.9.5", + "version": "3.10.3", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868" + "reference": "65edaca19a752730f290ec2fb89d593cb40afb43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/4a4e2eed3134036ee36a147ee0dac037dfa17868", - "reference": "4a4e2eed3134036ee36a147ee0dac037dfa17868", + "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": "13.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": "2.1.17", + "phpstan/phpstan": "2.1.30", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "9.6.23", - "slevomat/coding-standard": "8.16.2", - "squizlabs/php_codesniffer": "3.13.1", + "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" }, @@ -1025,7 +1026,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.9.5" + "source": "https://github.com/doctrine/dbal/tree/3.10.3" }, "funding": [ { @@ -1041,7 +1042,7 @@ "type": "tidelift" } ], - "time": "2025-06-15T22:40:05+00:00" + "time": "2025-10-09T09:05:12+00:00" }, { "name": "doctrine/deprecations", @@ -1093,20 +1094,21 @@ }, { "name": "doctrine/doctrine-bundle", - "version": "2.15.0", + "version": "2.18.1", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineBundle.git", - "reference": "d88294521a1bca943240adca65fa19ca8a7288c6" + "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/d88294521a1bca943240adca65fa19ca8a7288c6", - "reference": "d88294521a1bca943240adca65fa19ca8a7288c6", + "url": "https://api.github.com/repos/doctrine/DoctrineBundle/zipball/b769877014de053da0e5cbbb63d0ea2f3b2fea76", + "reference": "b769877014de053da0e5cbbb63d0ea2f3b2fea76", "shasum": "" }, "require": { "doctrine/dbal": "^3.7.0 || ^4.0", + "doctrine/deprecations": "^1.0", "doctrine/persistence": "^3.1 || ^4", "doctrine/sql-formatter": "^1.0.1", "php": "^8.1", @@ -1114,7 +1116,6 @@ "symfony/config": "^6.4 || ^7.0", "symfony/console": "^6.4 || ^7.0", "symfony/dependency-injection": "^6.4 || ^7.0", - "symfony/deprecation-contracts": "^2.1 || ^3", "symfony/doctrine-bridge": "^6.4.3 || ^7.0.3", "symfony/framework-bundle": "^6.4 || ^7.0", "symfony/service-contracts": "^2.5 || ^3" @@ -1129,18 +1130,17 @@ "require-dev": { "doctrine/annotations": "^1 || ^2", "doctrine/cache": "^1.11 || ^2.0", - "doctrine/coding-standard": "^13", - "doctrine/deprecations": "^1.0", + "doctrine/coding-standard": "^14", "doctrine/orm": "^2.17 || ^3.1", "friendsofphp/proxy-manager-lts": "^1.0", "phpstan/phpstan": "2.1.1", "phpstan/phpstan-phpunit": "2.0.3", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^9.6.22", + "phpunit/phpunit": "^10.5.53 || ^12.3.10", "psr/log": "^1.1.4 || ^2.0 || ^3.0", "symfony/doctrine-messenger": "^6.4 || ^7.0", + "symfony/expression-language": "^6.4 || ^7.0", "symfony/messenger": "^6.4 || ^7.0", - "symfony/phpunit-bridge": "^7.2", "symfony/property-info": "^6.4 || ^7.0", "symfony/security-bundle": "^6.4 || ^7.0", "symfony/stopwatch": "^6.4 || ^7.0", @@ -1150,7 +1150,7 @@ "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.13 || ^3.0.4" + "twig/twig": "^2.14.7 || ^3.0.4" }, "suggest": { "doctrine/orm": "The Doctrine ORM integration is optional in the bundle.", @@ -1195,7 +1195,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineBundle/issues", - "source": "https://github.com/doctrine/DoctrineBundle/tree/2.15.0" + "source": "https://github.com/doctrine/DoctrineBundle/tree/2.18.1" }, "funding": [ { @@ -1211,32 +1211,32 @@ "type": "tidelift" } ], - "time": "2025-06-16T19:53:58+00:00" + "time": "2025-11-05T14:42:10+00:00" }, { "name": "doctrine/doctrine-migrations-bundle", - "version": "3.4.2", + "version": "3.7.0", "source": { "type": "git", "url": "https://github.com/doctrine/DoctrineMigrationsBundle.git", - "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9" + "reference": "1e380c6dd8ac8488217f39cff6b77e367f1a644b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/DoctrineMigrationsBundle/zipball/5a6ac7120c2924c4c070a869d08b11ccf9e277b9", - "reference": "5a6ac7120c2924c4c070a869d08b11ccf9e277b9", + "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", "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", "phpstan/phpstan": "^1.4 || ^2", "phpstan/phpstan-deprecation-rules": "^1 || ^2", @@ -1244,8 +1244,8 @@ "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", - "symfony/var-exporter": "^5.4 || ^6 || ^7" + "symfony/phpunit-bridge": "^6.3 || ^7 || ^8", + "symfony/var-exporter": "^5.4 || ^6 || ^7 || ^8" }, "type": "symfony-bundle", "autoload": { @@ -1280,7 +1280,7 @@ ], "support": { "issues": "https://github.com/doctrine/DoctrineMigrationsBundle/issues", - "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.4.2" + "source": "https://github.com/doctrine/DoctrineMigrationsBundle/tree/3.7.0" }, "funding": [ { @@ -1296,7 +1296,7 @@ "type": "tidelift" } ], - "time": "2025-03-11T17:36:26+00:00" + "time": "2025-11-15T19:02:59+00:00" }, { "name": "doctrine/event-manager", @@ -1391,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/", @@ -1462,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": [ { @@ -1478,7 +1477,7 @@ "type": "tidelift" } ], - "time": "2024-02-18T20:23:39+00:00" + "time": "2025-08-10T19:31:58+00:00" }, { "name": "doctrine/instantiator", @@ -1629,16 +1628,16 @@ }, { "name": "doctrine/migrations", - "version": "3.9.1", + "version": "3.9.5", "source": { "type": "git", "url": "https://github.com/doctrine/migrations.git", - "reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999" + "reference": "1b823afbc40f932dae8272574faee53f2755eac5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/migrations/zipball/0f1e0c960ac29866d648a4f50142a74fe1cb6999", - "reference": "0f1e0c960ac29866d648a4f50142a74fe1cb6999", + "url": "https://api.github.com/repos/doctrine/migrations/zipball/1b823afbc40f932dae8272574faee53f2755eac5", + "reference": "1b823afbc40f932dae8272574faee53f2755eac5", "shasum": "" }, "require": { @@ -1648,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 || ^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.", @@ -1712,7 +1711,7 @@ ], "support": { "issues": "https://github.com/doctrine/migrations/issues", - "source": "https://github.com/doctrine/migrations/tree/3.9.1" + "source": "https://github.com/doctrine/migrations/tree/3.9.5" }, "funding": [ { @@ -1728,20 +1727,20 @@ "type": "tidelift" } ], - "time": "2025-06-27T07:19:23+00:00" + "time": "2025-11-20T11:15:36+00:00" }, { "name": "doctrine/orm", - "version": "2.20.5", + "version": "2.20.8", "source": { "type": "git", "url": "https://github.com/doctrine/orm.git", - "reference": "6307b4fa7d7e3845a756106977e3b48907622098" + "reference": "5bff0919a78c86238536a9b5396024fe3603b5d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/orm/zipball/6307b4fa7d7e3845a756106977e3b48907622098", - "reference": "6307b4fa7d7e3845a756106977e3b48907622098", + "url": "https://api.github.com/repos/doctrine/orm/zipball/5bff0919a78c86238536a9b5396024fe3603b5d1", + "reference": "5bff0919a78c86238536a9b5396024fe3603b5d1", "shasum": "" }, "require": { @@ -1768,14 +1767,13 @@ }, "require-dev": { "doctrine/annotations": "^1.13 || ^2", - "doctrine/coding-standard": "^9.0.2 || ^13.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 || 2.0.3", + "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.12.0", "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" @@ -1828,22 +1826,22 @@ ], "support": { "issues": "https://github.com/doctrine/orm/issues", - "source": "https://github.com/doctrine/orm/tree/2.20.5" + "source": "https://github.com/doctrine/orm/tree/2.20.8" }, - "time": "2025-06-24T17:50:46+00:00" + "time": "2025-11-10T13:35:45+00:00" }, { "name": "doctrine/persistence", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/doctrine/persistence.git", - "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff" + "reference": "d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/0ea965320cec355dba75031c1b23d4c78362e3ff", - "reference": "0ea965320cec355dba75031c1b23d4c78362e3ff", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0", + "reference": "d59e6ef7caffe6a30f4b6f9e9079a75f52c64ae0", "shasum": "" }, "require": { @@ -1855,11 +1853,11 @@ "doctrine/common": "<2.10" }, "require-dev": { - "doctrine/coding-standard": "^12", + "doctrine/coding-standard": "^12 || ^14", "doctrine/common": "^3.0", - "phpstan/phpstan": "1.12.7", - "phpstan/phpstan-phpunit": "^1", - "phpstan/phpstan-strict-rules": "^1.1", + "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" }, @@ -1910,7 +1908,7 @@ ], "support": { "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/3.4.0" + "source": "https://github.com/doctrine/persistence/tree/3.4.3" }, "funding": [ { @@ -1926,30 +1924,30 @@ "type": "tidelift" } ], - "time": "2024-10-30T19:48:12+00:00" + "time": "2025-10-21T15:21:39+00:00" }, { "name": "doctrine/sql-formatter", - "version": "1.5.2", + "version": "1.5.3", "source": { "type": "git", "url": "https://github.com/doctrine/sql-formatter.git", - "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8" + "reference": "a8af23a8e9d622505baa2997465782cbe8bb7fc7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/sql-formatter/zipball/d6d00aba6fd2957fe5216fe2b7673e9985db20c8", - "reference": "d6d00aba6fd2957fe5216fe2b7673e9985db20c8", + "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" + "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" @@ -1979,9 +1977,9 @@ ], "support": { "issues": "https://github.com/doctrine/sql-formatter/issues", - "source": "https://github.com/doctrine/sql-formatter/tree/1.5.2" + "source": "https://github.com/doctrine/sql-formatter/tree/1.5.3" }, - "time": "2025-01-24T11:45:48+00:00" + "time": "2025-10-26T09:35:14+00:00" }, { "name": "evenement/evenement", @@ -2032,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": { @@ -2051,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" }, @@ -2081,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": [ { @@ -2089,7 +2087,7 @@ "type": "github" } ], - "time": "2024-08-06T10:04:20+00:00" + "time": "2025-08-14T07:29:31+00:00" }, { "name": "firebase/php-jwt", @@ -2156,59 +2154,57 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.76.0", + "version": "v3.90.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "0e3c484cef0ae9314b0f85986a36296087432c40" + "reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/0e3c484cef0ae9314b0f85986a36296087432c40", - "reference": "0e3c484cef0ae9314b0f85986a36296087432c40", + "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.5", "ext-filter": "*", "ext-hash": "*", "ext-json": "*", "ext-tokenizer": "*", - "fidry/cpu-core-counter": "^1.2", + "fidry/cpu-core-counter": "^1.3", "php": "^7.4 || ^8.0", "react/child-process": "^0.6.6", - "react/event-loop": "^1.0", - "react/promise": "^2.11 || ^3.0", - "react/socket": "^1.0", - "react/stream": "^1.0", + "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.45 || ^6.4.13 || ^7.0", - "symfony/event-dispatcher": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/filesystem": "^5.4.45 || ^6.4.13 || ^7.0", - "symfony/finder": "^5.4.45 || ^6.4.17 || ^7.0", - "symfony/options-resolver": "^5.4.45 || ^6.4.16 || ^7.0", - "symfony/polyfill-mbstring": "^1.32", - "symfony/polyfill-php80": "^1.32", - "symfony/polyfill-php81": "^1.32", - "symfony/process": "^5.4.47 || ^6.4.20 || ^7.2", - "symfony/stopwatch": "^5.4.45 || ^6.4.19 || ^7.0" - }, - "require-dev": { - "facile-it/paraunit": "^1.3.1 || ^2.6", - "infection/infection": "^0.29.14", - "justinrainbow/json-schema": "^5.3 || ^6.4", + "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.8", - "php-cs-fixer/accessible-object": "^1.1", + "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.23 || ^10.5.47 || ^11.5.25", - "symfony/polyfill-php84": "^1.32", - "symfony/var-dumper": "^5.4.48 || ^6.4.23 || ^7.3.1", - "symfony/yaml": "^5.4.45 || ^6.4.23 || ^7.3.1" + "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", @@ -2249,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.76.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.90.0" }, "funding": [ { @@ -2257,26 +2253,26 @@ "type": "github" } ], - "time": "2025-06-30T14:15:06+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", @@ -2327,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": [ { @@ -2339,7 +2335,7 @@ "type": "tidelift" } ], - "time": "2024-03-20T12:50:41+00:00" + "time": "2025-10-28T10:28:17+00:00" }, { "name": "gesdinet/jwt-refresh-token-bundle", @@ -2423,22 +2419,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.9.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", - "reference": "7b2f29fe81dc4da0ca0ea7d42107a0845946ea77", + "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" @@ -2529,7 +2525,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.9.3" + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" }, "funding": [ { @@ -2545,20 +2541,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:37:11+00:00" + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/7c69f28996b0a6920945dd20b3857e499d9ca96c", - "reference": "7c69f28996b0a6920945dd20b3857e499d9ca96c", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { @@ -2566,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": { @@ -2612,7 +2608,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.2.0" + "source": "https://github.com/guzzle/promises/tree/2.3.0" }, "funding": [ { @@ -2628,20 +2624,20 @@ "type": "tidelift" } ], - "time": "2025-03-27T13:27:01+00:00" + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.7.1", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/c2270caaabe631b3b44c85f99e5a04bbb8060d16", - "reference": "c2270caaabe631b3b44c85f99e5a04bbb8060d16", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { @@ -2657,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" @@ -2728,7 +2724,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.7.1" + "source": "https://github.com/guzzle/psr7/tree/2.8.0" }, "funding": [ { @@ -2744,7 +2740,7 @@ "type": "tidelift" } ], - "time": "2025-03-27T12:30:47+00:00" + "time": "2025-08-23T21:21:41+00:00" }, { "name": "imagine/imagine", @@ -3065,26 +3061,26 @@ }, { "name": "kubawerlos/php-cs-fixer-custom-fixers", - "version": "v3.27.2", + "version": "v3.35.1", "source": { "type": "git", "url": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers.git", - "reference": "09a29566891d4214da2c1c429e7857f40397ef50" + "reference": "2a35f80ae24ca77443a7af1599c3a3db1b6bd395" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kubawerlos/php-cs-fixer-custom-fixers/zipball/09a29566891d4214da2c1c429e7857f40397ef50", - "reference": "09a29566891d4214da2c1c429e7857f40397ef50", + "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.22 || 10.5.45 || ^11.5.7" + "phpunit/phpunit": "^9.6.24 || ^10.5.51 || ^11.5.32" }, "type": "library", "autoload": { @@ -3105,7 +3101,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.27.2" + "source": "https://github.com/kubawerlos/php-cs-fixer-custom-fixers/tree/v3.35.1" }, "funding": [ { @@ -3113,31 +3109,31 @@ "type": "github" } ], - "time": "2025-06-28T11:13:24+00:00" + "time": "2025-09-28T18:43:35+00:00" }, { "name": "laminas/laminas-code", - "version": "4.16.0", + "version": "4.17.0", "source": { "type": "git", "url": "https://github.com/laminas/laminas-code.git", - "reference": "1793e78dad4108b594084d05d1fb818b85b110af" + "reference": "40d61e2899ec17c5d08bbc0a2d586b3ca17ab9bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-code/zipball/1793e78dad4108b594084d05d1fb818b85b110af", - "reference": "1793e78dad4108b594084d05d1fb818b85b110af", + "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 || ~8.4.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": "^3.0.0", "laminas/laminas-stdlib": "^3.18.0", - "phpunit/phpunit": "^10.5.37", + "phpunit/phpunit": "^10.5.58", "psalm/plugin-phpunit": "^0.19.0", "vimeo/psalm": "^5.15.0" }, @@ -3176,38 +3172,38 @@ "type": "community_bridge" } ], - "time": "2024-11-20T13:15:13+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": { @@ -3228,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": [ { @@ -3240,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.5.0", + "version": "5.6.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "a835af59b030d3f2967725697cf88300f579088e" + "reference": "bb3e9f21e4196e8afc41def81ef649c164bca25e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/a835af59b030d3f2967725697cf88300f579088e", - "reference": "a835af59b030d3f2967725697cf88300f579088e", + "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": { @@ -3301,7 +3297,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/5.5.0" + "source": "https://github.com/lcobucci/jwt/tree/5.6.0" }, "funding": [ { @@ -3313,26 +3309,26 @@ "type": "patreon" } ], - "time": "2025-01-26T21:29:45+00:00" + "time": "2025-10-17T11:30:53+00:00" }, { "name": "league/oauth2-client", - "version": "2.8.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-client.git", - "reference": "9df2924ca644736c835fc60466a3a60390d334f9" + "reference": "26e8c5da4f3d78cede7021e09b1330a0fc093d5e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/9df2924ca644736c835fc60466a3a60390d334f9", - "reference": "9df2924ca644736c835fc60466a3a60390d334f9", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/26e8c5da4f3d78cede7021e09b1330a0fc093d5e", + "reference": "26e8c5da4f3d78cede7021e09b1330a0fc093d5e", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", - "php": "^7.1 || >=8.0.0 <8.5.0" + "php": "^7.1 || >=8.0.0 <8.6.0" }, "require-dev": { "mockery/mockery": "^1.3.5", @@ -3376,9 +3372,9 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-client/issues", - "source": "https://github.com/thephpleague/oauth2-client/tree/2.8.1" + "source": "https://github.com/thephpleague/oauth2-client/tree/2.9.0" }, - "time": "2025-02-26T04:37:30+00:00" + "time": "2025-11-25T22:17:17+00:00" }, { "name": "lexik/jwt-authentication-bundle", @@ -3501,22 +3497,23 @@ }, { "name": "liip/imagine-bundle", - "version": "2.13.3", + "version": "2.15.0", "source": { "type": "git", "url": "https://github.com/liip/LiipImagineBundle.git", - "reference": "3faccde327f91368e51d05ecad49a9cd915abd81" + "reference": "f8c98a5a962806f26571db219412b64266c763d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/liip/LiipImagineBundle/zipball/3faccde327f91368e51d05ecad49a9cd915abd81", - "reference": "3faccde327f91368e51d05ecad49a9cd915abd81", + "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", @@ -3601,22 +3598,22 @@ ], "support": { "issues": "https://github.com/liip/LiipImagineBundle/issues", - "source": "https://github.com/liip/LiipImagineBundle/tree/2.13.3" + "source": "https://github.com/liip/LiipImagineBundle/tree/2.15.0" }, - "time": "2024-12-12T09:38:23+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": { @@ -3668,9 +3665,9 @@ ], "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", @@ -3844,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": { @@ -3900,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", @@ -3984,35 +3984,35 @@ }, { "name": "pentatrion/vite-bundle", - "version": "v8.2.0", + "version": "v8.2.3", "source": { "type": "git", "url": "https://github.com/lhapaipai/vite-bundle.git", - "reference": "e4cc14b4586cff1d55f51f6eebe6f62a0d9d7b17" + "reference": "354d90eebc702950daba6adcd2b93930de61812c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lhapaipai/vite-bundle/zipball/e4cc14b4586cff1d55f51f6eebe6f62a0d9d7b17", - "reference": "e4cc14b4586cff1d55f51f6eebe6f62a0d9d7b17", + "url": "https://api.github.com/repos/lhapaipai/vite-bundle/zipball/354d90eebc702950daba6adcd2b93930de61812c", + "reference": "354d90eebc702950daba6adcd2b93930de61812c", "shasum": "" }, "require": { "php": "^8.0", - "symfony/asset": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/config": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/http-client": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/twig-bundle": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/asset": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/config": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/dependency-injection": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/http-client": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/http-kernel": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/twig-bundle": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.9", "phpstan/phpstan": "^1.8", "phpstan/phpstan-symfony": "^1.3", "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^4.4 || ^5.0 || ^6.0 || ^7.0", - "symfony/web-link": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/phpunit-bridge": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/web-link": "^4.4 || ^5.0 || ^6.0 || ^7.0 || ^8.0" }, "type": "symfony-bundle", "autoload": { @@ -4039,9 +4039,9 @@ ], "support": { "issues": "https://github.com/lhapaipai/vite-bundle/issues", - "source": "https://github.com/lhapaipai/vite-bundle/tree/v8.2.0" + "source": "https://github.com/lhapaipai/vite-bundle/tree/v8.2.3" }, - "time": "2025-06-24T10:50:50+00:00" + "time": "2025-11-16T22:02:23+00:00" }, { "name": "php-http/discovery", @@ -4286,16 +4286,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.2", + "version": "5.6.5", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" + "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", - "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/90614c73d3800e187615e2dd236ad0e2a01bf761", + "reference": "90614c73d3800e187615e2dd236ad0e2a01bf761", "shasum": "" }, "require": { @@ -4344,22 +4344,22 @@ "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.6.2" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.5" }, - "time": "2025-04-13T19:20:35+00:00" + "time": "2025-11-27T19:50:05+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.10.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a" + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/679e3ce485b99e84c775d28e2e96fade9a7fb50a", - "reference": "679e3ce485b99e84c775d28e2e96fade9a7fb50a", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/92a98ada2b93d9b201a613cb5a33584dde25f195", + "reference": "92a98ada2b93d9b201a613cb5a33584dde25f195", "shasum": "" }, "require": { @@ -4402,9 +4402,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.10.0" + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.12.0" }, - "time": "2024-11-09T15:12:26+00:00" + "time": "2025-11-21T15:09:14+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -5112,16 +5112,16 @@ }, { "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": { @@ -5176,7 +5176,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": [ { @@ -5184,20 +5184,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": { @@ -5248,7 +5248,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": [ { @@ -5256,27 +5256,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", @@ -5321,7 +5321,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": [ { @@ -5329,20 +5329,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": { @@ -5401,7 +5401,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": [ { @@ -5409,7 +5409,7 @@ "type": "open_collective" } ], - "time": "2024-07-26T10:38:09+00:00" + "time": "2025-11-19T20:47:34+00:00" }, { "name": "react/stream", @@ -5648,16 +5648,16 @@ }, { "name": "symfony/asset", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/asset.git", - "reference": "2466c17d61d14539cddf77e57ebb9cc971185302" + "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/asset/zipball/2466c17d61d14539cddf77e57ebb9cc971185302", - "reference": "2466c17d61d14539cddf77e57ebb9cc971185302", + "url": "https://api.github.com/repos/symfony/asset/zipball/cfee7c0d64be113383db74a2fdd65d426b7f3aab", + "reference": "cfee7c0d64be113383db74a2fdd65d426b7f3aab", "shasum": "" }, "require": { @@ -5697,7 +5697,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.13" + "source": "https://github.com/symfony/asset/tree/v6.4.24" }, "funding": [ { @@ -5708,25 +5708,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-07-10T08:14:14+00:00" }, { "name": "symfony/cache", - "version": "v6.4.23", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b" + "reference": "31628f36fc97c5714d181b3a8d29efb85c6a7677" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/c88690befb8d4a85dc321fb78d677507f5eb141b", - "reference": "c88690befb8d4a85dc321fb78d677507f5eb141b", + "url": "https://api.github.com/repos/symfony/cache/zipball/31628f36fc97c5714d181b3a8d29efb85c6a7677", + "reference": "31628f36fc97c5714d181b3a8d29efb85c6a7677", "shasum": "" }, "require": { @@ -5793,7 +5797,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.23" + "source": "https://github.com/symfony/cache/tree/v6.4.28" }, "funding": [ { @@ -5804,12 +5808,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": "2025-06-27T18:31:36+00:00" + "time": "2025-10-30T08:37:02+00:00" }, { "name": "symfony/cache-contracts", @@ -5889,16 +5897,16 @@ }, { "name": "symfony/clock", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "b2bf55c4dd115003309eafa87ee7df9ed3dde81b" + "reference": "5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/b2bf55c4dd115003309eafa87ee7df9ed3dde81b", - "reference": "b2bf55c4dd115003309eafa87ee7df9ed3dde81b", + "url": "https://api.github.com/repos/symfony/clock/zipball/5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8", + "reference": "5e15a9c9aeeb44a99f7cf24aa75aa9607795f6f8", "shasum": "" }, "require": { @@ -5943,7 +5951,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v6.4.13" + "source": "https://github.com/symfony/clock/tree/v6.4.24" }, "funding": [ { @@ -5954,25 +5962,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-25T14:18:03+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/config", - "version": "v6.4.22", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7" + "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/af5917a3b1571f54689e56677a3f06440d2fe4c7", - "reference": "af5917a3b1571f54689e56677a3f06440d2fe4c7", + "url": "https://api.github.com/repos/symfony/config/zipball/15947c18ef3ddb0b2f4ec936b9e90e2520979f62", + "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62", "shasum": "" }, "require": { @@ -6018,7 +6030,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.22" + "source": "https://github.com/symfony/config/tree/v6.4.28" }, "funding": [ { @@ -6029,25 +6041,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": "2025-05-14T06:00:01+00:00" + "time": "2025-11-01T19:52:02+00:00" }, { "name": "symfony/console", - "version": "v6.4.23", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93" + "reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9056771b8eca08d026cd3280deeec3cfd99c4d93", - "reference": "9056771b8eca08d026cd3280deeec3cfd99c4d93", + "url": "https://api.github.com/repos/symfony/console/zipball/13d3176cf8ad8ced24202844e9f95af11e2959fc", + "reference": "13d3176cf8ad8ced24202844e9f95af11e2959fc", "shasum": "" }, "require": { @@ -6112,7 +6128,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.23" + "source": "https://github.com/symfony/console/tree/v6.4.27" }, "funding": [ { @@ -6123,25 +6139,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": "2025-06-27T19:37:22+00:00" + "time": "2025-10-06T10:25:16+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b" + "reference": "5f311eaf0b321f8ec640f6bae12da43a14026898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0d9f24f3de0a83573fce5c9ed025d6306c6e166b", - "reference": "0d9f24f3de0a83573fce5c9ed025d6306c6e166b", + "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5f311eaf0b321f8ec640f6bae12da43a14026898", + "reference": "5f311eaf0b321f8ec640f6bae12da43a14026898", "shasum": "" }, "require": { @@ -6193,7 +6213,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.23" + "source": "https://github.com/symfony/dependency-injection/tree/v6.4.26" }, "funding": [ { @@ -6204,12 +6224,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": "2025-06-23T06:49:06+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6280,16 +6304,16 @@ }, { "name": "symfony/doctrine-bridge", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/doctrine-bridge.git", - "reference": "ef360932b8b342c0360b768b97776a12d5242db6" + "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/ef360932b8b342c0360b768b97776a12d5242db6", - "reference": "ef360932b8b342c0360b768b97776a12d5242db6", + "url": "https://api.github.com/repos/symfony/doctrine-bridge/zipball/c14bb5a9125c411e73354954940e06b6e7fcc344", + "reference": "c14bb5a9125c411e73354954940e06b6e7fcc344", "shasum": "" }, "require": { @@ -6368,7 +6392,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.23" + "source": "https://github.com/symfony/doctrine-bridge/tree/v6.4.26" }, "funding": [ { @@ -6379,25 +6403,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": "2025-06-26T11:46:10+00:00" + "time": "2025-09-26T15:07:38+00:00" }, { "name": "symfony/dom-crawler", - "version": "v6.4.23", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "22210aacb35dbadd772325d759d17bce2374a84d" + "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/22210aacb35dbadd772325d759d17bce2374a84d", - "reference": "22210aacb35dbadd772325d759d17bce2374a84d", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/976302990f9f2a6d4c07206836dd4ca77cae9524", + "reference": "976302990f9f2a6d4c07206836dd4ca77cae9524", "shasum": "" }, "require": { @@ -6435,7 +6463,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.23" + "source": "https://github.com/symfony/dom-crawler/tree/v6.4.25" }, "funding": [ { @@ -6446,25 +6474,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": "2025-06-13T12:10:00+00:00" + "time": "2025-08-05T18:56:08+00:00" }, { "name": "symfony/dotenv", - "version": "v6.4.16", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/dotenv.git", - "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5" + "reference": "234b6c602f12b00693f4b0d1054386fb30dfc8ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dotenv/zipball/1ac5e7e7e862d4d574258daf08bd569ba926e4a5", - "reference": "1ac5e7e7e862d4d574258daf08bd569ba926e4a5", + "url": "https://api.github.com/repos/symfony/dotenv/zipball/234b6c602f12b00693f4b0d1054386fb30dfc8ff", + "reference": "234b6c602f12b00693f4b0d1054386fb30dfc8ff", "shasum": "" }, "require": { @@ -6509,7 +6541,7 @@ "environment" ], "support": { - "source": "https://github.com/symfony/dotenv/tree/v6.4.16" + "source": "https://github.com/symfony/dotenv/tree/v6.4.24" }, "funding": [ { @@ -6520,25 +6552,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-11-27T11:08:19+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/error-handler", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa" + "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/b088e0b175c30b4e06d8085200fa465b586f44fa", - "reference": "b088e0b175c30b4e06d8085200fa465b586f44fa", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/41bedcaec5b72640b0ec2096547b75fda72ead6c", + "reference": "41bedcaec5b72640b0ec2096547b75fda72ead6c", "shasum": "" }, "require": { @@ -6584,7 +6620,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.23" + "source": "https://github.com/symfony/error-handler/tree/v6.4.26" }, "funding": [ { @@ -6595,25 +6631,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": "2025-06-13T07:39:48+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.4.13", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" + "reference": "b0cf3162020603587363f0551cd3be43958611ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", - "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/b0cf3162020603587363f0551cd3be43958611ff", + "reference": "b0cf3162020603587363f0551cd3be43958611ff", "shasum": "" }, "require": { @@ -6664,7 +6704,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.13" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.25" }, "funding": [ { @@ -6675,12 +6715,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-25T14:18:03+00:00" + "time": "2025-08-13T09:41:44+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6760,16 +6804,16 @@ }, { "name": "symfony/expression-language", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/expression-language.git", - "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df" + "reference": "1ea0adaa53539ea7e70821ae9de49ebe03ae7091" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/expression-language/zipball/3524904fb026356a5230cd197f9a4e6a61e0e7df", - "reference": "3524904fb026356a5230cd197f9a4e6a61e0e7df", + "url": "https://api.github.com/repos/symfony/expression-language/zipball/1ea0adaa53539ea7e70821ae9de49ebe03ae7091", + "reference": "1ea0adaa53539ea7e70821ae9de49ebe03ae7091", "shasum": "" }, "require": { @@ -6804,7 +6848,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.13" + "source": "https://github.com/symfony/expression-language/tree/v6.4.24" }, "funding": [ { @@ -6815,25 +6859,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-09T08:40:40+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/filesystem", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" + "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", - "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", + "reference": "75ae2edb7cdcc0c53766c30b0a2512b8df574bd8", "shasum": "" }, "require": { @@ -6870,7 +6918,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.13" + "source": "https://github.com/symfony/filesystem/tree/v6.4.24" }, "funding": [ { @@ -6881,25 +6929,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-07-10T08:14:14+00:00" }, { "name": "symfony/finder", - "version": "v6.4.24", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "73089124388c8510efb8d2d1689285d285937b08" + "reference": "a1b6aa435d2fba50793b994a839c32b6064f063b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/73089124388c8510efb8d2d1689285d285937b08", - "reference": "73089124388c8510efb8d2d1689285d285937b08", + "url": "https://api.github.com/repos/symfony/finder/zipball/a1b6aa435d2fba50793b994a839c32b6064f063b", + "reference": "a1b6aa435d2fba50793b994a839c32b6064f063b", "shasum": "" }, "require": { @@ -6934,7 +6986,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.24" + "source": "https://github.com/symfony/finder/tree/v6.4.27" }, "funding": [ { @@ -6954,35 +7006,36 @@ "type": "tidelift" } ], - "time": "2025-07-15T12:02:45+00:00" + "time": "2025-10-15T18:32:00+00:00" }, { "name": "symfony/flex", - "version": "v2.7.1", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/symfony/flex.git", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155" + "reference": "9cd384775973eabbf6e8b05784dda279fc67c28d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/flex/zipball/4ae50d368415a06820739e54d38a4a29d6df9155", - "reference": "4ae50d368415a06820739e54d38a4a29d6df9155", + "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": { @@ -7006,7 +7059,7 @@ "description": "Composer plugin for Symfony", "support": { "issues": "https://github.com/symfony/flex/issues", - "source": "https://github.com/symfony/flex/tree/v2.7.1" + "source": "https://github.com/symfony/flex/tree/v2.10.0" }, "funding": [ { @@ -7017,25 +7070,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": "2025-05-28T14:22:54+00:00" + "time": "2025-11-16T09:38:19+00:00" }, { "name": "symfony/framework-bundle", - "version": "v6.4.23", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22" + "reference": "ee58c2a73218d8f4763824e1414c5f9b4519c91f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ff892d3ab4b8aa35921bc2120a4b31d57948fe22", - "reference": "ff892d3ab4b8aa35921bc2120a4b31d57948fe22", + "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/ee58c2a73218d8f4763824e1414c5f9b4519c91f", + "reference": "ee58c2a73218d8f4763824e1414c5f9b4519c91f", "shasum": "" }, "require": { @@ -7155,7 +7212,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.23" + "source": "https://github.com/symfony/framework-bundle/tree/v6.4.27" }, "funding": [ { @@ -7166,25 +7223,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": "2025-06-26T21:24:02+00:00" + "time": "2025-10-15T17:35:09+00:00" }, { "name": "symfony/http-client", - "version": "v6.4.23", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "19f11e742b94dcfd968a54f5381bb9082a88cb57" + "reference": "c9e69c185c4a845f9d46958cdb0dc7aa847f3981" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/19f11e742b94dcfd968a54f5381bb9082a88cb57", - "reference": "19f11e742b94dcfd968a54f5381bb9082a88cb57", + "url": "https://api.github.com/repos/symfony/http-client/zipball/c9e69c185c4a845f9d46958cdb0dc7aa847f3981", + "reference": "c9e69c185c4a845f9d46958cdb0dc7aa847f3981", "shasum": "" }, "require": { @@ -7192,6 +7253,7 @@ "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-client-contracts": "~3.4.4|^3.5.2", + "symfony/polyfill-php83": "^1.29", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -7248,7 +7310,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.23" + "source": "https://github.com/symfony/http-client/tree/v6.4.28" }, "funding": [ { @@ -7259,12 +7321,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": "2025-06-27T20:02:31+00:00" + "time": "2025-11-05T17:39:22+00:00" }, { "name": "symfony/http-client-contracts", @@ -7346,16 +7412,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.23", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3" + "reference": "b03d11e015552a315714c127d8d1e0f9e970ec88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/452d19f945ee41345fd8a50c18b60783546b7bd3", - "reference": "452d19f945ee41345fd8a50c18b60783546b7bd3", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/b03d11e015552a315714c127d8d1e0f9e970ec88", + "reference": "b03d11e015552a315714c127d8d1e0f9e970ec88", "shasum": "" }, "require": { @@ -7403,7 +7469,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.23" + "source": "https://github.com/symfony/http-foundation/tree/v6.4.29" }, "funding": [ { @@ -7414,25 +7480,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": "2025-05-26T09:17:58+00:00" + "time": "2025-11-08T16:40:12+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.23", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a" + "reference": "18818b48f54c1d2bd92b41d82d8345af50b15658" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/2bb2cba685aabd859f22cf6946554e8e7f3c329a", - "reference": "2bb2cba685aabd859f22cf6946554e8e7f3c329a", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/18818b48f54c1d2bd92b41d82d8345af50b15658", + "reference": "18818b48f54c1d2bd92b41d82d8345af50b15658", "shasum": "" }, "require": { @@ -7517,7 +7587,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.23" + "source": "https://github.com/symfony/http-kernel/tree/v6.4.29" }, "funding": [ { @@ -7528,25 +7598,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": "2025-06-28T08:14:51+00:00" + "time": "2025-11-12T11:22:59+00:00" }, { "name": "symfony/mime", - "version": "v6.4.21", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "fec8aa5231f3904754955fad33c2db50594d22d1" + "reference": "61ab9681cdfe315071eb4fa79b6ad6ab030a9235" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/fec8aa5231f3904754955fad33c2db50594d22d1", - "reference": "fec8aa5231f3904754955fad33c2db50594d22d1", + "url": "https://api.github.com/repos/symfony/mime/zipball/61ab9681cdfe315071eb4fa79b6ad6ab030a9235", + "reference": "61ab9681cdfe315071eb4fa79b6ad6ab030a9235", "shasum": "" }, "require": { @@ -7602,7 +7676,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.21" + "source": "https://github.com/symfony/mime/tree/v6.4.26" }, "funding": [ { @@ -7613,25 +7687,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": "2025-04-27T13:27:38+00:00" + "time": "2025-09-16T08:22:30+00:00" }, { "name": "symfony/monolog-bridge", - "version": "v6.4.13", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bridge.git", - "reference": "9d14621e59f22c2b6d030d92d37ffe5ae1e60452" + "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/9d14621e59f22c2b6d030d92d37ffe5ae1e60452", - "reference": "9d14621e59f22c2b6d030d92d37ffe5ae1e60452", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/d2f4b68e3247cf44d93f48545c8c072a75c17e5b", + "reference": "d2f4b68e3247cf44d93f48545c8c072a75c17e5b", "shasum": "" }, "require": { @@ -7681,7 +7759,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.13" + "source": "https://github.com/symfony/monolog-bridge/tree/v6.4.28" }, "funding": [ { @@ -7692,53 +7770,52 @@ "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-14T08:49:08+00:00" + "time": "2025-10-30T19:57:08+00:00" }, { "name": "symfony/monolog-bundle", - "version": "v3.10.0", + "version": "v3.11.0", "source": { "type": "git", "url": "https://github.com/symfony/monolog-bundle.git", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181" + "reference": "e12eb92655b234cd50c21cda648088847a7ec777" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", - "reference": "414f951743f4aa1fd0f5bf6a0e9c16af3fe7f181", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/e12eb92655b234cd50c21cda648088847a7ec777", + "reference": "e12eb92655b234cd50c21cda648088847a7ec777", "shasum": "" }, "require": { + "composer-runtime-api": "^2.0", "monolog/monolog": "^1.25.1 || ^2.0 || ^3.0", - "php": ">=7.2.5", - "symfony/config": "^5.4 || ^6.0 || ^7.0", - "symfony/dependency-injection": "^5.4 || ^6.0 || ^7.0", - "symfony/http-kernel": "^5.4 || ^6.0 || ^7.0", - "symfony/monolog-bridge": "^5.4 || ^6.0 || ^7.0" + "php": ">=8.1", + "symfony/config": "^6.4 || ^7.0", + "symfony/dependency-injection": "^6.4 || ^7.0", + "symfony/deprecation-contracts": "^2.5 || ^3.0", + "symfony/http-kernel": "^6.4 || ^7.0", + "symfony/monolog-bridge": "^6.4 || ^7.0", + "symfony/polyfill-php84": "^1.30" }, "require-dev": { - "symfony/console": "^5.4 || ^6.0 || ^7.0", - "symfony/phpunit-bridge": "^6.3 || ^7.0", - "symfony/yaml": "^5.4 || ^6.0 || ^7.0" + "symfony/console": "^6.4 || ^7.0", + "symfony/phpunit-bridge": "^7.3.3", + "symfony/yaml": "^6.4 || ^7.0" }, "type": "symfony-bundle", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "autoload": { "psr-4": { - "Symfony\\Bundle\\MonologBundle\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Bundle\\MonologBundle\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7762,7 +7839,7 @@ ], "support": { "issues": "https://github.com/symfony/monolog-bundle/issues", - "source": "https://github.com/symfony/monolog-bundle/tree/v3.10.0" + "source": "https://github.com/symfony/monolog-bundle/tree/v3.11.0" }, "funding": [ { @@ -7773,25 +7850,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": "2023-11-06T17:08:13+00:00" + "time": "2025-11-27T09:16:19+00:00" }, { "name": "symfony/options-resolver", - "version": "v6.4.16", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "368128ad168f20e22c32159b9f761e456cec0c78" + "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/368128ad168f20e22c32159b9f761e456cec0c78", - "reference": "368128ad168f20e22c32159b9f761e456cec0c78", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28e7e2db8a73e9511df892d36445f61314bbebe", + "reference": "d28e7e2db8a73e9511df892d36445f61314bbebe", "shasum": "" }, "require": { @@ -7829,7 +7910,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v6.4.16" + "source": "https://github.com/symfony/options-resolver/tree/v6.4.25" }, "funding": [ { @@ -7840,25 +7921,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-11-20T10:57:02+00:00" + "time": "2025-08-04T17:06:28+00:00" }, { "name": "symfony/password-hasher", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/password-hasher.git", - "reference": "e97a1b31f60b8bdfc1fdedab4398538da9441d47" + "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/password-hasher/zipball/e97a1b31f60b8bdfc1fdedab4398538da9441d47", - "reference": "e97a1b31f60b8bdfc1fdedab4398538da9441d47", + "url": "https://api.github.com/repos/symfony/password-hasher/zipball/dcab5ac87450aaed26483ba49c2ce86808da7557", + "reference": "dcab5ac87450aaed26483ba49c2ce86808da7557", "shasum": "" }, "require": { @@ -7901,7 +7986,7 @@ "password" ], "support": { - "source": "https://github.com/symfony/password-hasher/tree/v6.4.13" + "source": "https://github.com/symfony/password-hasher/tree/v6.4.24" }, "funding": [ { @@ -7912,25 +7997,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-25T14:18:03+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.32.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": { @@ -7979,7 +8068,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" }, "funding": [ { @@ -7990,16 +8079,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-06-27T09:58:17+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", @@ -8062,7 +8155,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" }, "funding": [ { @@ -8073,6 +8166,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" @@ -8082,7 +8179,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -8143,7 +8240,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" }, "funding": [ { @@ -8154,6 +8251,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" @@ -8163,7 +8264,7 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", @@ -8224,7 +8325,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" }, "funding": [ { @@ -8235,6 +8336,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" @@ -8312,7 +8417,7 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", @@ -8372,7 +8477,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" }, "funding": [ { @@ -8383,6 +8488,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" @@ -8392,7 +8501,7 @@ }, { "name": "symfony/polyfill-php81", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", @@ -8448,7 +8557,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.33.0" }, "funding": [ { @@ -8459,6 +8568,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" @@ -8468,16 +8581,16 @@ }, { "name": "symfony/polyfill-php83", - "version": "v1.32.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": { @@ -8524,7 +8637,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0" }, "funding": [ { @@ -8535,25 +8648,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-07-08T02:45:35+00:00" }, { "name": "symfony/polyfill-php84", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php84.git", - "reference": "000df7860439609837bbe28670b0be15783b7fbf" + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/000df7860439609837bbe28670b0be15783b7fbf", - "reference": "000df7860439609837bbe28670b0be15783b7fbf", + "url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/d8ced4d875142b6a7426000426b8abc631d6b191", + "reference": "d8ced4d875142b6a7426000426b8abc631d6b191", "shasum": "" }, "require": { @@ -8600,7 +8717,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php84/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-php84/tree/v1.33.0" }, "funding": [ { @@ -8611,16 +8728,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": "2025-02-20T12:04:08+00:00" + "time": "2025-06-24T13:30:11+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.32.0", + "version": "v1.33.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", @@ -8679,7 +8800,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.32.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.33.0" }, "funding": [ { @@ -8690,6 +8811,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" @@ -8699,16 +8824,16 @@ }, { "name": "symfony/process", - "version": "v6.4.20", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e2a61c16af36c9a07e5c9906498b73e091949a20" + "reference": "48bad913268c8cafabbf7034b39c8bb24fbc5ab8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e2a61c16af36c9a07e5c9906498b73e091949a20", - "reference": "e2a61c16af36c9a07e5c9906498b73e091949a20", + "url": "https://api.github.com/repos/symfony/process/zipball/48bad913268c8cafabbf7034b39c8bb24fbc5ab8", + "reference": "48bad913268c8cafabbf7034b39c8bb24fbc5ab8", "shasum": "" }, "require": { @@ -8740,7 +8865,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.4.20" + "source": "https://github.com/symfony/process/tree/v6.4.26" }, "funding": [ { @@ -8751,25 +8876,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": "2025-03-10T17:11:00+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/property-access", - "version": "v6.4.18", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/property-access.git", - "reference": "80e0378f2f058b60d87dedc3c760caec882e992c" + "reference": "fedc771326d4978a7d3167fa009a509b06a2e168" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-access/zipball/80e0378f2f058b60d87dedc3c760caec882e992c", - "reference": "80e0378f2f058b60d87dedc3c760caec882e992c", + "url": "https://api.github.com/repos/symfony/property-access/zipball/fedc771326d4978a7d3167fa009a509b06a2e168", + "reference": "fedc771326d4978a7d3167fa009a509b06a2e168", "shasum": "" }, "require": { @@ -8817,7 +8946,7 @@ "reflection" ], "support": { - "source": "https://github.com/symfony/property-access/tree/v6.4.18" + "source": "https://github.com/symfony/property-access/tree/v6.4.25" }, "funding": [ { @@ -8828,25 +8957,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-12-16T14:42:05+00:00" + "time": "2025-08-12T15:42:57+00:00" }, { "name": "symfony/property-info", - "version": "v6.4.18", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/property-info.git", - "reference": "94d18e5cc11a37fd92856d38b61d9cdf72536a1e" + "reference": "1056ae3621eeddd78d7c5ec074f1c1784324eec6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/property-info/zipball/94d18e5cc11a37fd92856d38b61d9cdf72536a1e", - "reference": "94d18e5cc11a37fd92856d38b61d9cdf72536a1e", + "url": "https://api.github.com/repos/symfony/property-info/zipball/1056ae3621eeddd78d7c5ec074f1c1784324eec6", + "reference": "1056ae3621eeddd78d7c5ec074f1c1784324eec6", "shasum": "" }, "require": { @@ -8903,7 +9036,7 @@ "validator" ], "support": { - "source": "https://github.com/symfony/property-info/tree/v6.4.18" + "source": "https://github.com/symfony/property-info/tree/v6.4.24" }, "funding": [ { @@ -8914,25 +9047,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": "2025-01-21T10:52:27+00:00" + "time": "2025-07-14T16:38:25+00:00" }, { "name": "symfony/proxy-manager-bridge", - "version": "v6.4.13", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/proxy-manager-bridge.git", - "reference": "8932b572e147e80fb498045c580eb14215197529" + "reference": "9ecac7f98ad685d474394dbd06dab29bab4e18a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/8932b572e147e80fb498045c580eb14215197529", - "reference": "8932b572e147e80fb498045c580eb14215197529", + "url": "https://api.github.com/repos/symfony/proxy-manager-bridge/zipball/9ecac7f98ad685d474394dbd06dab29bab4e18a6", + "reference": "9ecac7f98ad685d474394dbd06dab29bab4e18a6", "shasum": "" }, "require": { @@ -8970,7 +9107,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.13" + "source": "https://github.com/symfony/proxy-manager-bridge/tree/v6.4.28" }, "funding": [ { @@ -8981,25 +9118,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-25T14:18:03+00:00" + "time": "2025-11-02T18:11:54+00:00" }, { "name": "symfony/routing", - "version": "v6.4.22", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670" + "reference": "ae064a6d9cf39507f9797658465a2ca702965fa8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/1f5234e8457164a3a0038a4c0a4ba27876a9c670", - "reference": "1f5234e8457164a3a0038a4c0a4ba27876a9c670", + "url": "https://api.github.com/repos/symfony/routing/zipball/ae064a6d9cf39507f9797658465a2ca702965fa8", + "reference": "ae064a6d9cf39507f9797658465a2ca702965fa8", "shasum": "" }, "require": { @@ -9053,7 +9194,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.22" + "source": "https://github.com/symfony/routing/tree/v6.4.28" }, "funding": [ { @@ -9064,25 +9205,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": "2025-04-27T16:08:38+00:00" + "time": "2025-10-31T16:43:05+00:00" }, { "name": "symfony/runtime", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/runtime.git", - "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f" + "reference": "59933ca737fd60fad548241b6d879cd0e4be31ab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/runtime/zipball/ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", - "reference": "ef1f03c2ab1144ac4ef7744b9e026bdb06f2f88f", + "url": "https://api.github.com/repos/symfony/runtime/zipball/59933ca737fd60fad548241b6d879cd0e4be31ab", + "reference": "59933ca737fd60fad548241b6d879cd0e4be31ab", "shasum": "" }, "require": { @@ -9132,7 +9277,7 @@ "runtime" ], "support": { - "source": "https://github.com/symfony/runtime/tree/v6.4.23" + "source": "https://github.com/symfony/runtime/tree/v6.4.26" }, "funding": [ { @@ -9143,25 +9288,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": "2025-06-13T07:44:14+00:00" + "time": "2025-09-11T15:30:54+00:00" }, { "name": "symfony/security-bundle", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/security-bundle.git", - "reference": "3db1460f539b23e74a119981ea6b3002302250bc" + "reference": "b83773107a5b83a5507df9e88bd50d495f6e8b72" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-bundle/zipball/3db1460f539b23e74a119981ea6b3002302250bc", - "reference": "3db1460f539b23e74a119981ea6b3002302250bc", + "url": "https://api.github.com/repos/symfony/security-bundle/zipball/b83773107a5b83a5507df9e88bd50d495f6e8b72", + "reference": "b83773107a5b83a5507df9e88bd50d495f6e8b72", "shasum": "" }, "require": { @@ -9244,7 +9393,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.23" + "source": "https://github.com/symfony/security-bundle/tree/v6.4.26" }, "funding": [ { @@ -9255,25 +9404,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": "2025-06-23T20:18:57+00:00" + "time": "2025-09-22T15:03:07+00:00" }, { "name": "symfony/security-core", - "version": "v6.4.23", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/security-core.git", - "reference": "527780a0482e592530174ca90e6189f64cdf6569" + "reference": "673018434b38e504eb04ca3c6d7e2e7c86735bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/527780a0482e592530174ca90e6189f64cdf6569", - "reference": "527780a0482e592530174ca90e6189f64cdf6569", + "url": "https://api.github.com/repos/symfony/security-core/zipball/673018434b38e504eb04ca3c6d7e2e7c86735bfb", + "reference": "673018434b38e504eb04ca3c6d7e2e7c86735bfb", "shasum": "" }, "require": { @@ -9330,7 +9483,7 @@ "description": "Symfony Security Component - Core Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-core/tree/v6.4.23" + "source": "https://github.com/symfony/security-core/tree/v6.4.27" }, "funding": [ { @@ -9341,25 +9494,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": "2025-05-30T08:33:44+00:00" + "time": "2025-10-23T19:49:35+00:00" }, { "name": "symfony/security-csrf", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/security-csrf.git", - "reference": "c34421b7d34efbaef5d611ab2e646a0ec464ffe3" + "reference": "9a1efc8c10b86bcedc9233affd10c716b54ca1b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-csrf/zipball/c34421b7d34efbaef5d611ab2e646a0ec464ffe3", - "reference": "c34421b7d34efbaef5d611ab2e646a0ec464ffe3", + "url": "https://api.github.com/repos/symfony/security-csrf/zipball/9a1efc8c10b86bcedc9233affd10c716b54ca1b7", + "reference": "9a1efc8c10b86bcedc9233affd10c716b54ca1b7", "shasum": "" }, "require": { @@ -9398,7 +9555,7 @@ "description": "Symfony Security Component - CSRF Library", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-csrf/tree/v6.4.13" + "source": "https://github.com/symfony/security-csrf/tree/v6.4.24" }, "funding": [ { @@ -9409,25 +9566,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-25T14:18:03+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/security-http", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/security-http.git", - "reference": "815fcda8122a7850bf6d5d842ce03c20445295bb" + "reference": "6c2e236f0fc3e0853770a5574ef7af471486ba4c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/security-http/zipball/815fcda8122a7850bf6d5d842ce03c20445295bb", - "reference": "815fcda8122a7850bf6d5d842ce03c20445295bb", + "url": "https://api.github.com/repos/symfony/security-http/zipball/6c2e236f0fc3e0853770a5574ef7af471486ba4c", + "reference": "6c2e236f0fc3e0853770a5574ef7af471486ba4c", "shasum": "" }, "require": { @@ -9486,7 +9647,7 @@ "description": "Symfony Security Component - HTTP Integration", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/security-http/tree/v6.4.23" + "source": "https://github.com/symfony/security-http/tree/v6.4.26" }, "funding": [ { @@ -9497,25 +9658,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": "2025-06-23T20:18:57+00:00" + "time": "2025-09-05T18:17:25+00:00" }, { "name": "symfony/serializer", - "version": "v6.4.23", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/serializer.git", - "reference": "b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06" + "reference": "28779bbdb398cac3421d0e51f7ca669e4a27c5ac" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/serializer/zipball/b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06", - "reference": "b40a697a2bb2c3d841a1f9e34a8a9f50bf9d1d06", + "url": "https://api.github.com/repos/symfony/serializer/zipball/28779bbdb398cac3421d0e51f7ca669e4a27c5ac", + "reference": "28779bbdb398cac3421d0e51f7ca669e4a27c5ac", "shasum": "" }, "require": { @@ -9584,7 +9749,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.23" + "source": "https://github.com/symfony/serializer/tree/v6.4.27" }, "funding": [ { @@ -9595,25 +9760,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": "2025-06-27T15:34:20+00:00" + "time": "2025-10-08T04:24:22+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", - "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43", + "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43", "shasum": "" }, "require": { @@ -9667,7 +9836,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.1" }, "funding": [ { @@ -9678,25 +9847,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": "2025-04-25T09:37:31+00:00" + "time": "2025-07-15T11:30:57+00:00" }, { "name": "symfony/stopwatch", - "version": "v6.4.19", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c" + "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", - "reference": "dfe1481c12c06266d0c3d58c0cb4b09bd497ab9c", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/b67e94e06a05d9572c2fa354483b3e13e3cb1898", + "reference": "b67e94e06a05d9572c2fa354483b3e13e3cb1898", "shasum": "" }, "require": { @@ -9729,7 +9902,7 @@ "description": "Provides a way to profile code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/stopwatch/tree/v6.4.19" + "source": "https://github.com/symfony/stopwatch/tree/v6.4.24" }, "funding": [ { @@ -9740,25 +9913,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": "2025-02-21T10:06:30+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/string", - "version": "v6.4.21", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" + "reference": "5621f039a71a11c87c106c1c598bdcd04a19aeea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", - "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", + "url": "https://api.github.com/repos/symfony/string/zipball/5621f039a71a11c87c106c1c598bdcd04a19aeea", + "reference": "5621f039a71a11c87c106c1c598bdcd04a19aeea", "shasum": "" }, "require": { @@ -9772,7 +9949,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", @@ -9815,7 +9991,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.21" + "source": "https://github.com/symfony/string/tree/v6.4.26" }, "funding": [ { @@ -9826,25 +10002,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": "2025-04-18T15:23:29+00:00" + "time": "2025-09-11T14:32:46+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.6.0", + "version": "v3.6.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d" + "reference": "65a8bc82080447fae78373aa10f8d13b38338977" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/df210c7a2573f1913b2d17cc95f90f53a73d8f7d", - "reference": "df210c7a2573f1913b2d17cc95f90f53a73d8f7d", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/65a8bc82080447fae78373aa10f8d13b38338977", + "reference": "65a8bc82080447fae78373aa10f8d13b38338977", "shasum": "" }, "require": { @@ -9893,7 +10073,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.6.1" }, "funding": [ { @@ -9904,25 +10084,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-27T08:32:26+00:00" + "time": "2025-07-15T13:41:35+00:00" }, { "name": "symfony/twig-bridge", - "version": "v6.4.22", + "version": "v6.4.25", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d" + "reference": "9d13e87591c9de3221c8d6f23cd9a2b5958607bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/04ab306a2f2c9dbd46f4363383812954f704af9d", - "reference": "04ab306a2f2c9dbd46f4363383812954f704af9d", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9d13e87591c9de3221c8d6f23cd9a2b5958607bf", + "reference": "9d13e87591c9de3221c8d6f23cd9a2b5958607bf", "shasum": "" }, "require": { @@ -10002,7 +10186,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.22" + "source": "https://github.com/symfony/twig-bridge/tree/v6.4.25" }, "funding": [ { @@ -10013,25 +10197,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": "2025-05-16T08:23:44+00:00" + "time": "2025-08-13T09:41:44+00:00" }, { "name": "symfony/twig-bundle", - "version": "v6.4.23", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/twig-bundle.git", - "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd" + "reference": "3b48b6e8225495c6d2438828982b4d219ca565ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/ef970ed7eb9e547d21628e4c803de0943759cbcd", - "reference": "ef970ed7eb9e547d21628e4c803de0943759cbcd", + "url": "https://api.github.com/repos/symfony/twig-bundle/zipball/3b48b6e8225495c6d2438828982b4d219ca565ba", + "reference": "3b48b6e8225495c6d2438828982b4d219ca565ba", "shasum": "" }, "require": { @@ -10086,7 +10274,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.23" + "source": "https://github.com/symfony/twig-bundle/tree/v6.4.24" }, "funding": [ { @@ -10097,25 +10285,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": "2025-06-20T20:02:07+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/uid", - "version": "v6.4.23", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "9c8592da78d7ee6af52011eef593350d87e814c0" + "reference": "17da16a750541a42cf2183935e0f6008316c23f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/9c8592da78d7ee6af52011eef593350d87e814c0", - "reference": "9c8592da78d7ee6af52011eef593350d87e814c0", + "url": "https://api.github.com/repos/symfony/uid/zipball/17da16a750541a42cf2183935e0f6008316c23f7", + "reference": "17da16a750541a42cf2183935e0f6008316c23f7", "shasum": "" }, "require": { @@ -10160,7 +10352,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.4.23" + "source": "https://github.com/symfony/uid/tree/v6.4.24" }, "funding": [ { @@ -10171,25 +10363,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": "2025-06-26T08:06:12+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/validator", - "version": "v6.4.23", + "version": "v6.4.29", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "6506760ab57e7cda5bde9cdaed736526162284bc" + "reference": "99df8a769e64e399f510166141ea74f450e8dd1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/6506760ab57e7cda5bde9cdaed736526162284bc", - "reference": "6506760ab57e7cda5bde9cdaed736526162284bc", + "url": "https://api.github.com/repos/symfony/validator/zipball/99df8a769e64e399f510166141ea74f450e8dd1d", + "reference": "99df8a769e64e399f510166141ea74f450e8dd1d", "shasum": "" }, "require": { @@ -10257,7 +10453,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v6.4.23" + "source": "https://github.com/symfony/validator/tree/v6.4.29" }, "funding": [ { @@ -10268,25 +10464,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": "2025-06-26T07:25:45+00:00" + "time": "2025-11-06T20:26:06+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600" + "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", - "reference": "d55b1834cdbfcc31bc2cd7e095ba5ed9a88f6600", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cfae1497a2f1eaad78dbc0590311c599c7178d4a", + "reference": "cfae1497a2f1eaad78dbc0590311c599c7178d4a", "shasum": "" }, "require": { @@ -10298,7 +10498,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", @@ -10342,7 +10541,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.23" + "source": "https://github.com/symfony/var-dumper/tree/v6.4.26" }, "funding": [ { @@ -10353,25 +10552,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": "2025-06-27T15:05:27+00:00" + "time": "2025-09-25T15:37:27+00:00" }, { "name": "symfony/var-exporter", - "version": "v6.4.22", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/var-exporter.git", - "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9" + "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-exporter/zipball/f28cf841f5654955c9f88ceaf4b9dc29571988a9", - "reference": "f28cf841f5654955c9f88ceaf4b9dc29571988a9", + "url": "https://api.github.com/repos/symfony/var-exporter/zipball/466fcac5fa2e871f83d31173f80e9c2684743bfc", + "reference": "466fcac5fa2e871f83d31173f80e9c2684743bfc", "shasum": "" }, "require": { @@ -10419,7 +10622,7 @@ "serialize" ], "support": { - "source": "https://github.com/symfony/var-exporter/tree/v6.4.22" + "source": "https://github.com/symfony/var-exporter/tree/v6.4.26" }, "funding": [ { @@ -10430,25 +10633,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": "2025-05-14T13:00:13+00:00" + "time": "2025-09-11T09:57:09+00:00" }, { "name": "symfony/web-link", - "version": "v6.4.22", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/web-link.git", - "reference": "8595204221c4307b5fd30644a225b0b952082b18" + "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-link/zipball/8595204221c4307b5fd30644a225b0b952082b18", - "reference": "8595204221c4307b5fd30644a225b0b952082b18", + "url": "https://api.github.com/repos/symfony/web-link/zipball/75ffbb304f26a716969863328c8c6a11eadcfa5a", + "reference": "75ffbb304f26a716969863328c8c6a11eadcfa5a", "shasum": "" }, "require": { @@ -10502,7 +10709,7 @@ "push" ], "support": { - "source": "https://github.com/symfony/web-link/tree/v6.4.22" + "source": "https://github.com/symfony/web-link/tree/v6.4.24" }, "funding": [ { @@ -10513,25 +10720,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": "2025-05-16T08:23:44+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/yaml", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b" + "reference": "0fc8b966fd0dcaab544ae59bfc3a433f048c17b0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/93e29e0deb5f1b2e360adfb389a20d25eb81a27b", - "reference": "93e29e0deb5f1b2e360adfb389a20d25eb81a27b", + "url": "https://api.github.com/repos/symfony/yaml/zipball/0fc8b966fd0dcaab544ae59bfc3a433f048c17b0", + "reference": "0fc8b966fd0dcaab544ae59bfc3a433f048c17b0", "shasum": "" }, "require": { @@ -10574,7 +10785,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v6.4.23" + "source": "https://github.com/symfony/yaml/tree/v6.4.26" }, "funding": [ { @@ -10585,25 +10796,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": "2025-06-03T06:46:12+00:00" + "time": "2025-09-26T15:07:38+00:00" }, { "name": "twig/twig", - "version": "v3.21.1", + "version": "v3.22.0", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d" + "reference": "4509984193026de413baf4ba80f68590a7f2c51d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/285123877d4dd97dd7c11842ac5fb7e86e60d81d", - "reference": "285123877d4dd97dd7c11842ac5fb7e86e60d81d", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/4509984193026de413baf4ba80f68590a7f2c51d", + "reference": "4509984193026de413baf4ba80f68590a7f2c51d", "shasum": "" }, "require": { @@ -10657,7 +10872,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.21.1" + "source": "https://github.com/twigphp/Twig/tree/v3.22.0" }, "funding": [ { @@ -10669,20 +10884,20 @@ "type": "tidelift" } ], - "time": "2025-05-03T07:21:55+00:00" + "time": "2025-10-29T15:56:47+00:00" }, { "name": "vich/uploader-bundle", - "version": "v2.7.0", + "version": "v2.8.1", "source": { "type": "git", "url": "https://github.com/dustin10/VichUploaderBundle.git", - "reference": "8a8cce134fc686caadf6828956f8ddd2b383fe74" + "reference": "0619f0831003a16c65c6e038833430318705cbe1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/8a8cce134fc686caadf6828956f8ddd2b383fe74", - "reference": "8a8cce134fc686caadf6828956f8ddd2b383fe74", + "url": "https://api.github.com/repos/dustin10/VichUploaderBundle/zipball/0619f0831003a16c65c6e038833430318705cbe1", + "reference": "0619f0831003a16c65c6e038833430318705cbe1", "shasum": "" }, "require": { @@ -10775,34 +10990,34 @@ ], "support": { "issues": "https://github.com/dustin10/VichUploaderBundle/issues", - "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.7.0" + "source": "https://github.com/dustin10/VichUploaderBundle/tree/v2.8.1" }, - "time": "2025-06-12T06:59:34+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": { @@ -10833,9 +11048,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", @@ -10897,43 +11112,36 @@ "packages-dev": [ { "name": "amphp/amp", - "version": "v2.6.4", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", - "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "url": "https://api.github.com/repos/amphp/amp/zipball/fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "react/promise": "^2", - "vimeo/psalm": "^3.12" + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.x-dev" - } - }, "autoload": { "files": [ - "lib/functions.php", - "lib/Internal/functions.php" + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" ], "psr-4": { - "Amp\\": "lib" + "Amp\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -10941,10 +11149,6 @@ "MIT" ], "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, { "name": "Aaron Piotrowski", "email": "aaron@trowski.com" @@ -10956,6 +11160,10 @@ { "name": "Niklas Keller", "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" } ], "description": "A non-blocking concurrency framework for PHP applications.", @@ -10972,9 +11180,8 @@ "promise" ], "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/v3.1.1" }, "funding": [ { @@ -10982,41 +11189,45 @@ "type": "github" } ], - "time": "2024-03-21T18:52:26+00:00" + "time": "2025-08-27T21:42:00+00:00" }, { "name": "amphp/byte-stream", - "version": "v1.8.2", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", "shasum": "" }, "require": { - "amphp/amp": "^2", - "php": ">=7.1" + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" }, "type": "library", "autoload": { "files": [ - "lib/functions.php" + "src/functions.php", + "src/Internal/functions.php" ], "psr-4": { - "Amp\\ByteStream\\": "lib" + "Amp\\ByteStream\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11045,7 +11256,7 @@ ], "support": { "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" }, "funding": [ { @@ -11053,94 +11264,112 @@ "type": "github" } ], - "time": "2024-04-13T18:00:56+00:00" + "time": "2025-03-16T17:10:27+00:00" }, { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", + "name": "amphp/cache", + "version": "v2.0.1", "source": { "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", "shasum": "" }, "require": { - "php": ">=5.3.2" + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" }, "type": "library", "autoload": { "psr-4": { - "XdgBaseDir\\": "src/" + "Amp\\Cache\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "implementation of xdg base directory specification for php", + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" }, - "time": "2019-12-04T15:06:13+00:00" + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" }, { - "name": "doctrine/data-fixtures", - "version": "1.8.2", + "name": "amphp/dns", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5" + "url": "https://github.com/amphp/dns.git", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/6fb221da56dae2011b33d47508e3b8aeb1d91db5", - "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1.0", - "doctrine/persistence": "^2.0 || ^3.0", - "php": "^7.4 || ^8.0", - "symfony/polyfill-php80": "^1" - }, - "conflict": { - "doctrine/dbal": "<3.5 || >=5", - "doctrine/orm": "<2.14 || >=4", - "doctrine/phpcr-odm": "<1.3.0" + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/process": "^2", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "ext-json": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "doctrine/annotations": "^1.12 || ^2", - "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": "*", - "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" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", - "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", - "doctrine/orm": "For loading ORM fixtures", - "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" }, "type": "library", "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { - "Doctrine\\Common\\DataFixtures\\": "src" + "Amp\\Dns\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11149,90 +11378,91 @@ ], "authors": [ { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" } ], - "description": "Data Fixtures for all Doctrine Object Managers", - "homepage": "https://www.doctrine-project.org", + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", "keywords": [ - "database" + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" ], "support": { - "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.8.2" + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.4.0" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", - "type": "tidelift" + "url": "https://github.com/amphp", + "type": "github" } ], - "time": "2025-06-10T07:00:05+00:00" + "time": "2025-01-19T15:43:40+00:00" }, { - "name": "ergebnis/composer-normalize", - "version": "2.47.0", + "name": "amphp/parallel", + "version": "v2.3.2", "source": { "type": "git", - "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "ed24b9f8901f8fbafeca98f662eaca39427f0544" + "url": "https://github.com/amphp/parallel.git", + "reference": "321b45ae771d9c33a068186b24117e3cd1c48dce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/ed24b9f8901f8fbafeca98f662eaca39427f0544", - "reference": "ed24b9f8901f8fbafeca98f662eaca39427f0544", + "url": "https://api.github.com/repos/amphp/parallel/zipball/321b45ae771d9c33a068186b24117e3cd1c48dce", + "reference": "321b45ae771d9c33a068186b24117e3cd1c48dce", "shasum": "" }, "require": { - "composer-plugin-api": "^2.0.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 || ^6.0.0", - "localheinz/diff": "^1.2.0", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/pipeline": "^1", + "amphp/process": "^2", + "amphp/serialization": "^1", + "amphp/socket": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1" }, "require-dev": { - "composer/composer": "^2.8.3", - "ergebnis/license": "^2.6.0", - "ergebnis/php-cs-fixer-config": "^6.46.0", - "ergebnis/phpunit-slow-test-detector": "^2.19.1", - "fakerphp/faker": "^1.24.1", - "infection/infection": "~0.26.6", - "phpstan/extension-installer": "^1.4.3", - "phpstan/phpstan": "^2.1.11", - "phpstan/phpstan-deprecation-rules": "^2.0.1", - "phpstan/phpstan-phpunit": "^2.0.6", - "phpstan/phpstan-strict-rules": "^2.0.4", - "phpunit/phpunit": "^9.6.20", - "rector/rector": "^2.0.11", - "symfony/filesystem": "^5.4.41" - }, - "type": "composer-plugin", - "extra": { - "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", - "branch-alias": { - "dev-main": "2.44-dev" - }, - "plugin-optional": true, - "composer-normalize": { - "indent-size": 2, - "indent-style": "space" - } + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" }, + "type": "library", "autoload": { + "files": [ + "src/Context/functions.php", + "src/Context/Internal/functions.php", + "src/Ipc/functions.php", + "src/Worker/functions.php" + ], "psr-4": { - "Ergebnis\\Composer\\Normalize\\": "src/" + "Amp\\Parallel\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11241,61 +11471,796 @@ ], "authors": [ { - "name": "Andreas Möller", - "email": "am@localheinz.com", - "homepage": "https://localheinz.com" + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" } ], - "description": "Provides a composer plugin for normalizing composer.json.", - "homepage": "https://github.com/ergebnis/composer-normalize", + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", "keywords": [ - "composer", - "normalize", - "normalizer", - "plugin" + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" ], "support": { - "issues": "https://github.com/ergebnis/composer-normalize/issues", + "issues": "https://github.com/amphp/parallel/issues", + "source": "https://github.com/amphp/parallel/tree/v2.3.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-08-27T21:55:40+00:00" + }, + { + "name": "amphp/parser", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "shasum": "" + }, + "require": { + "php": ">=7.4" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Parser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "7b52598c2e9105ebcddf247fc523161581930367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", + "reference": "7b52598c2e9105ebcddf247fc523161581930367", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T16:33:53+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-08-03T19:31:26+00:00" + }, + { + "name": "danog/advanced-json-rpc", + "version": "v3.2.2", + "source": { + "type": "git", + "url": "https://github.com/danog/php-advanced-json-rpc.git", + "reference": "aadb1c4068a88c3d0530cfe324b067920661efcb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/danog/php-advanced-json-rpc/zipball/aadb1c4068a88c3d0530cfe324b067920661efcb", + "reference": "aadb1c4068a88c3d0530cfe324b067920661efcb", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^5", + "php": ">=8.1", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + }, + "replace": { + "felixfbecker/php-advanced-json-rpc": "^3" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/danog/php-advanced-json-rpc/issues", + "source": "https://github.com/danog/php-advanced-json-rpc/tree/v3.2.2" + }, + "time": "2025-02-14T10:55:15+00:00" + }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/data-fixtures", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5" + }, + "dist": { + "type": "zip", + "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", + "symfony/polyfill-php80": "^1" + }, + "conflict": { + "doctrine/dbal": "<3.5 || >=5", + "doctrine/orm": "<2.14 || >=4", + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "doctrine/annotations": "^1.12 || ^2", + "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": "*", + "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" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "database" + ], + "support": { + "issues": "https://github.com/doctrine/data-fixtures/issues", + "source": "https://github.com/doctrine/data-fixtures/tree/1.8.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", + "type": "tidelift" + } + ], + "time": "2025-06-10T07:00:05+00:00" + }, + { + "name": "ergebnis/composer-normalize", + "version": "2.48.2", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/composer-normalize.git", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.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 || ^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.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", + "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" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\Composer\\Normalize\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a composer plugin for normalizing composer.json.", + "homepage": "https://github.com/ergebnis/composer-normalize", + "keywords": [ + "composer", + "normalize", + "normalizer", + "plugin" + ], + "support": { + "issues": "https://github.com/ergebnis/composer-normalize/issues", "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/composer-normalize" }, - "time": "2025-04-15T11:09:27+00:00" + "time": "2025-09-06T11:42:34+00:00" }, { "name": "ergebnis/json", - "version": "1.4.0", + "version": "1.6.0", "source": { "type": "git", "url": "https://github.com/ergebnis/json.git", - "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69" + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json/zipball/7656ac2aa6c2ca4408f96f599e9a17a22c464f69", - "reference": "7656ac2aa6c2ca4408f96f599e9a17a22c464f69", + "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/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", "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.18", - "rector/rector": "^1.2.10" + "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" @@ -11327,20 +12292,20 @@ "security": "https://github.com/ergebnis/json/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json" }, - "time": "2024-11-17T11:51:22+00:00" + "time": "2025-09-06T09:08:45+00:00" }, { "name": "ergebnis/json-normalizer", - "version": "4.9.0", + "version": "4.10.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-normalizer.git", - "reference": "cc4dcf3890448572a2d9bea97133c4d860e59fb1" + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/cc4dcf3890448572a2d9bea97133c4d860e59fb1", - "reference": "cc4dcf3890448572a2d9bea97133c4d860e59fb1", + "url": "https://api.github.com/repos/ergebnis/json-normalizer/zipball/77961faf2c651c3f05977b53c6c68e8434febf62", + "reference": "77961faf2c651c3f05977b53c6c68e8434febf62", "shasum": "" }, "require": { @@ -11350,7 +12315,7 @@ "ergebnis/json-schema-validator": "^4.2.0", "ext-json": "*", "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" + "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", @@ -11375,7 +12340,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.8-dev" + "dev-main": "4.11-dev" }, "composer-normalize": { "indent-size": 2, @@ -11409,24 +12374,24 @@ "security": "https://github.com/ergebnis/json-normalizer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-normalizer" }, - "time": "2025-04-10T13:13:04+00:00" + "time": "2025-09-06T09:18:13+00:00" }, { "name": "ergebnis/json-pointer", - "version": "3.6.0", + "version": "3.7.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-pointer.git", - "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798" + "reference": "43bef355184e9542635e35dd2705910a3df4c236" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-pointer/zipball/4fc85d8edb74466d282119d8d9541ec7cffc0798", - "reference": "4fc85d8edb74466d282119d8d9541ec7cffc0798", + "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", @@ -11447,7 +12412,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.8-dev" }, "composer-normalize": { "indent-size": 2, @@ -11482,28 +12447,29 @@ "security": "https://github.com/ergebnis/json-pointer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-pointer" }, - "time": "2024-11-17T12:37:06+00:00" + "time": "2025-09-06T09:28:19+00:00" }, { "name": "ergebnis/json-printer", - "version": "3.7.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-printer.git", - "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82" + "reference": "211d73fc7ec6daf98568ee6ed6e6d133dee8503e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/ced41fce7854152f0e8f38793c2ffe59513cdd82", - "reference": "ced41fce7854152f0e8f38793c2ffe59513cdd82", + "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/composer-normalize": "^2.44.0", "ergebnis/data-provider": "^3.3.0", "ergebnis/license": "^2.5.0", "ergebnis/php-cs-fixer-config": "^6.37.0", @@ -11519,6 +12485,15 @@ "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/" @@ -11547,20 +12522,20 @@ "security": "https://github.com/ergebnis/json-printer/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-printer" }, - "time": "2024-11-17T11:20:51+00:00" + "time": "2025-09-06T09:59:26+00:00" }, { "name": "ergebnis/json-schema-validator", - "version": "4.4.0", + "version": "4.5.1", "source": { "type": "git", "url": "https://github.com/ergebnis/json-schema-validator.git", - "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec" + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/85f90c81f718aebba1d738800af83eeb447dc7ec", - "reference": "85f90c81f718aebba1d738800af83eeb447dc7ec", + "url": "https://api.github.com/repos/ergebnis/json-schema-validator/zipball/b739527a480a9e3651360ad351ea77e7e9019df2", + "reference": "b739527a480a9e3651360ad351ea77e7e9019df2", "shasum": "" }, "require": { @@ -11568,7 +12543,7 @@ "ergebnis/json-pointer": "^3.4.0", "ext-json": "*", "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" + "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.44.0", @@ -11589,7 +12564,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "4.4-dev" + "dev-main": "4.6-dev" }, "composer-normalize": { "indent-size": 2, @@ -11624,7 +12599,7 @@ "security": "https://github.com/ergebnis/json-schema-validator/blob/main/.github/SECURITY.md", "source": "https://github.com/ergebnis/json-schema-validator" }, - "time": "2024-11-18T06:32:28+00:00" + "time": "2025-09-06T11:37:35+00:00" }, { "name": "fakerphp/faker", @@ -11690,149 +12665,327 @@ "time": "2024-11-21T13:46:39+00:00" }, { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.3", "source": { "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9", "shasum": "" }, "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" + "php": ">=7.1" + }, + "require-dev": { + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "LanguageServerProtocol\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + } + ], + "description": "PHP classes for the Language Server Protocol", + "keywords": [ + "language", + "microsoft", + "php", + "server" + ], + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.3" + }, + "time": "2024-04-30T00:40:11+00:00" + }, + { + "name": "hautelook/alice-bundle", + "version": "2.13.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/AliceBundle.git", + "reference": "7b8cf62973853ec406ecb27f3b90b91a1b525a05" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/AliceBundle/zipball/7b8cf62973853ec406ecb27f3b90b91a1b525a05", + "reference": "7b8cf62973853ec406ecb27f3b90b91a1b525a05", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^1.5", + "doctrine/doctrine-bundle": "^2.5", + "doctrine/orm": "^2.10.0", + "doctrine/persistence": "^2.2 || ^3.0", + "php": "^8.2", + "psr/log": "^1.0 || ^2.0 || ^3.0", + "symfony/finder": "^6.4 || ^7.0", + "symfony/framework-bundle": "^6.4 || ^7.0", + "theofidry/alice-data-fixtures": "^1.5" + }, + "require-dev": { + "monolog/monolog": "^3.5", + "phpspec/prophecy": "^1.7", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "symfony/phpunit-bridge": "^6.4 || ^7.0" + }, + "type": "symfony-bundle", + "extra": { + "bin-dir": "bin", + "branch-alias": { + "dev-master": "2.x-dev" + }, + "sort-packages": true + }, + "autoload": { + "psr-4": { + "Hautelook\\AliceBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Baldur Rensch", + "email": "brensch@gmail.com" + }, + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com", + "homepage": "https://github.com/theofidry" + } + ], + "description": "Symfony bundle to manage fixtures with Alice and Faker.", + "keywords": [ + "Fixture", + "alice", + "faker", + "orm", + "symfony" + ], + "support": { + "issues": "https://github.com/theofidry/AliceBundle/issues", + "source": "https://github.com/theofidry/AliceBundle/tree/2.13.0" + }, + "time": "2023-12-03T23:53:29+00:00" + }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, "autoload": { "psr-4": { - "AdvancedJsonRpc\\": "lib/" + "Kelunik\\Certificate\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "ISC" + "MIT" ], "authors": [ { - "name": "Felix Becker", - "email": "felix.b@outlook.com" + "name": "Niklas Keller", + "email": "me@kelunik.com" } ], - "description": "A more advanced JSONRPC implementation", + "description": "Access certificate details and transform between different formats.", + "keywords": [ + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" + ], "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" }, - "time": "2021-06-11T22:34:44+00:00" + "time": "2023-02-03T21:26:53+00:00" }, { - "name": "felixfbecker/language-server-protocol", - "version": "v1.5.3", + "name": "league/uri", + "version": "7.6.0", "source": { "type": "git", - "url": "https://github.com/felixfbecker/php-language-server-protocol.git", - "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9" + "url": "https://github.com/thephpleague/uri.git", + "reference": "f625804987a0a9112d954f9209d91fec52182344" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/a9e113dbc7d849e35b8776da39edaf4313b7b6c9", - "reference": "a9e113dbc7d849e35b8776da39edaf4313b7b6c9", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/f625804987a0a9112d954f9209d91fec52182344", + "reference": "f625804987a0a9112d954f9209d91fec52182344", "shasum": "" }, "require": { - "php": ">=7.1" + "league/uri-interfaces": "^7.6", + "php": "^8.1", + "psr/http-factory": "^1" }, - "require-dev": { - "phpstan/phpstan": "*", - "squizlabs/php_codesniffer": "^3.1", - "vimeo/psalm": "^4.0" + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "league/uri-polyfill": "Needed to backport the PHP URI extension for older versions of PHP", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "7.x-dev" } }, "autoload": { "psr-4": { - "LanguageServerProtocol\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "ISC" + "MIT" ], "authors": [ { - "name": "Felix Becker", - "email": "felix.b@outlook.com" + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" } ], - "description": "PHP classes for the Language Server Protocol", + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", "keywords": [ - "language", - "microsoft", - "php", - "server" + "URN", + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc2141", + "rfc3986", + "rfc3987", + "rfc6570", + "rfc8141", + "uri", + "uri-template", + "url", + "ws" ], "support": { - "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", - "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.3" + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.6.0" }, - "time": "2024-04-30T00:40:11+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2025-11-18T12:17:23+00:00" }, { - "name": "hautelook/alice-bundle", - "version": "2.13.0", + "name": "league/uri-interfaces", + "version": "7.6.0", "source": { "type": "git", - "url": "https://github.com/theofidry/AliceBundle.git", - "reference": "7b8cf62973853ec406ecb27f3b90b91a1b525a05" + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/AliceBundle/zipball/7b8cf62973853ec406ecb27f3b90b91a1b525a05", - "reference": "7b8cf62973853ec406ecb27f3b90b91a1b525a05", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/ccbfb51c0445298e7e0b7f4481b942f589665368", + "reference": "ccbfb51c0445298e7e0b7f4481b942f589665368", "shasum": "" }, "require": { - "doctrine/data-fixtures": "^1.5", - "doctrine/doctrine-bundle": "^2.5", - "doctrine/orm": "^2.10.0", - "doctrine/persistence": "^2.2 || ^3.0", - "php": "^8.2", - "psr/log": "^1.0 || ^2.0 || ^3.0", - "symfony/finder": "^6.4 || ^7.0", - "symfony/framework-bundle": "^6.4 || ^7.0", - "theofidry/alice-data-fixtures": "^1.5" + "ext-filter": "*", + "php": "^8.1", + "psr/http-message": "^1.1 || ^2.0" }, - "require-dev": { - "monolog/monolog": "^3.5", - "phpspec/prophecy": "^1.7", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.5", - "symfony/phpunit-bridge": "^6.4 || ^7.0" + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle WHATWG URL", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, - "type": "symfony-bundle", + "type": "library", "extra": { - "bin-dir": "bin", "branch-alias": { - "dev-master": "2.x-dev" - }, - "sort-packages": true + "dev-master": "7.x-dev" + } }, "autoload": { "psr-4": { - "Hautelook\\AliceBundle\\": "src" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -11841,45 +12994,62 @@ ], "authors": [ { - "name": "Baldur Rensch", - "email": "brensch@gmail.com" - }, - { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com", - "homepage": "https://github.com/theofidry" + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" } ], - "description": "Symfony bundle to manage fixtures with Alice and Faker.", + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", + "homepage": "https://uri.thephpleague.com", "keywords": [ - "Fixture", - "alice", - "faker", - "orm", - "symfony" + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" ], "support": { - "issues": "https://github.com/theofidry/AliceBundle/issues", - "source": "https://github.com/theofidry/AliceBundle/tree/2.13.0" + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.6.0" }, - "time": "2023-12-03T23:53:29+00:00" + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2025-11-18T12:17:23+00:00" }, { "name": "localheinz/diff", - "version": "1.2.0", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/localheinz/diff.git", - "reference": "ec413943c2b518464865673fd5b38f7df867a010" + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/localheinz/diff/zipball/ec413943c2b518464865673fd5b38f7df867a010", - "reference": "ec413943c2b518464865673fd5b38f7df867a010", + "url": "https://api.github.com/repos/localheinz/diff/zipball/33bd840935970cda6691c23fc7d94ae764c0734c", + "reference": "33bd840935970cda6691c23fc7d94ae764c0734c", "shasum": "" }, "require": { - "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" + "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.0 || ^8.5.23", @@ -11915,22 +13085,22 @@ ], "support": { "issues": "https://github.com/localheinz/diff/issues", - "source": "https://github.com/localheinz/diff/tree/1.2.0" + "source": "https://github.com/localheinz/diff/tree/1.3.0" }, - "time": "2024-12-04T14:16:01+00:00" + "time": "2025-08-30T09:44:18+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.13.1", + "version": "1.13.4", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", - "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/07d290f0c47959fd5eed98c95ee5602db07e0b6a", + "reference": "07d290f0c47959fd5eed98c95ee5602db07e0b6a", "shasum": "" }, "require": { @@ -11969,7 +13139,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.4" }, "funding": [ { @@ -11977,7 +13147,7 @@ "type": "tidelift" } ], - "time": "2025-04-29T12:36:36+00:00" + "time": "2025-08-01T08:46:24+00:00" }, { "name": "nelmio/alice", @@ -12077,16 +13247,16 @@ }, { "name": "netresearch/jsonmapper", - "version": "v4.5.0", + "version": "v5.0.0", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5" + "reference": "8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8e76efb98ee8b6afc54687045e1b8dba55ac76e5", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c", + "reference": "8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c", "shasum": "" }, "require": { @@ -12122,31 +13292,33 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.5.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v5.0.0" }, - "time": "2024-09-08T10:13:13+00:00" + "time": "2024-09-08T10:20:00+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.4", + "version": "v5.6.2", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2" + "reference": "3a454ca033b9e06b63282ce19562e892747449bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/715f4d25e225bc47b293a8b997fe6ce99bf987d2", - "reference": "715f4d25e225bc47b293a8b997fe6ce99bf987d2", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb", + "reference": "3a454ca033b9e06b63282ce19562e892747449bb", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -12154,7 +13326,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.x-dev" } }, "autoload": { @@ -12178,9 +13350,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.4" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2" }, - "time": "2024-09-29T15:01:53+00:00" + "time": "2025-10-21T19:32:17+00:00" }, { "name": "phar-io/manifest", @@ -12302,16 +13474,11 @@ }, { "name": "phpstan/phpstan", - "version": "1.12.27", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpstan.git", - "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162" - }, + "version": "1.12.32", "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3a6e423c076ab39dfedc307e2ac627ef579db162", - "reference": "3a6e423c076ab39dfedc307e2ac627ef579db162", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2770dcdf5078d0b0d53f94317e06affe88419aa8", + "reference": "2770dcdf5078d0b0d53f94317e06affe88419aa8", "shasum": "" }, "require": { @@ -12356,7 +13523,7 @@ "type": "github" } ], - "time": "2025-05-21T20:51:45+00:00" + "time": "2025-09-30T10:16:31+00:00" }, { "name": "phpunit/php-code-coverage", @@ -12679,16 +13846,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.23", + "version": "9.6.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", - "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", + "reference": "9ecfec57835a5581bc888ea7e13b51eb55ab9dd3", "shasum": "" }, "require": { @@ -12699,7 +13866,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.13.1", + "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -12710,11 +13877,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", @@ -12762,7 +13929,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.23" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.29" }, "funding": [ { @@ -12786,27 +13953,27 @@ "type": "tidelift" } ], - "time": "2025-05-02T06:40:34+00:00" + "time": "2025-09-24T06:29:11+00:00" }, { "name": "psalm/plugin-symfony", - "version": "v5.2.6", + "version": "v5.2.7", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-symfony.git", - "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742" + "reference": "56dd7ba14c4ac9796e06077f00e45fbbecc640af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/1638f172b4ae5f283ee6b1b58fff3e44aa628742", - "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742", + "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/56dd7ba14c4ac9796e06077f00e45fbbecc640af", + "reference": "56dd7ba14c4ac9796e06077f00e45fbbecc640af", "shasum": "" }, "require": { "ext-simplexml": "*", - "php": "^8.1", + "php": ">=8.1", "symfony/framework-bundle": "^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "^5.16 || dev-master" + "vimeo/psalm": "^6 || dev-master" }, "require-dev": { "doctrine/annotations": "^1.8|^2", @@ -12849,9 +14016,9 @@ "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.6" + "source": "https://github.com/psalm/psalm-plugin-symfony/tree/v5.2.7" }, - "time": "2024-12-21T08:46:26+00:00" + "time": "2025-01-26T10:27:48+00:00" }, { "name": "rector/rector", @@ -12912,6 +14079,78 @@ ], "time": "2024-11-08T13:59:10+00:00" }, + { + "name": "revolt/event-loop", + "version": "v1.0.8", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/b6fc06dce8e9b523c9946138fa5e62181934f91c", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.8" + }, + "time": "2025-08-27T21:33:23+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -13081,16 +14320,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": { @@ -13143,15 +14382,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", @@ -13275,16 +14526,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": { @@ -13340,28 +14591,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": { @@ -13404,15 +14667,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", @@ -13585,16 +14860,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": { @@ -13636,15 +14911,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", @@ -13811,16 +15098,16 @@ }, { "name": "spatie/array-to-xml", - "version": "3.4.0", + "version": "3.4.3", "source": { "type": "git", "url": "https://github.com/spatie/array-to-xml.git", - "reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67" + "reference": "7b9202dccfe18d4e3a13303156d6bbcc1c61dabf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67", - "reference": "7dcfc67d60b0272926dabad1ec01f6b8a5fb5e67", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/7b9202dccfe18d4e3a13303156d6bbcc1c61dabf", + "reference": "7b9202dccfe18d4e3a13303156d6bbcc1c61dabf", "shasum": "" }, "require": { @@ -13863,7 +15150,7 @@ "xml" ], "support": { - "source": "https://github.com/spatie/array-to-xml/tree/3.4.0" + "source": "https://github.com/spatie/array-to-xml/tree/3.4.3" }, "funding": [ { @@ -13875,20 +15162,20 @@ "type": "github" } ], - "time": "2024-12-16T12:45:15+00:00" + "time": "2025-11-27T09:08:26+00:00" }, { "name": "symfony/browser-kit", - "version": "v6.4.19", + "version": "v6.4.28", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "ce95f3e3239159e7fa3be7690c6ce95a4714637f" + "reference": "067e301786bbb58048077fc10507aceb18226e23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/ce95f3e3239159e7fa3be7690c6ce95a4714637f", - "reference": "ce95f3e3239159e7fa3be7690c6ce95a4714637f", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/067e301786bbb58048077fc10507aceb18226e23", + "reference": "067e301786bbb58048077fc10507aceb18226e23", "shasum": "" }, "require": { @@ -13927,7 +15214,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.19" + "source": "https://github.com/symfony/browser-kit/tree/v6.4.28" }, "funding": [ { @@ -13938,25 +15225,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": "2025-02-14T11:23:16+00:00" + "time": "2025-10-16T22:35:35+00:00" }, { "name": "symfony/css-selector", - "version": "v6.4.13", + "version": "v6.4.24", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e" + "reference": "9b784413143701aa3c94ac1869a159a9e53e8761" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/cb23e97813c5837a041b73a6d63a9ddff0778f5e", - "reference": "cb23e97813c5837a041b73a6d63a9ddff0778f5e", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/9b784413143701aa3c94ac1869a159a9e53e8761", + "reference": "9b784413143701aa3c94ac1869a159a9e53e8761", "shasum": "" }, "require": { @@ -13992,7 +15283,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.4.13" + "source": "https://github.com/symfony/css-selector/tree/v6.4.24" }, "funding": [ { @@ -14003,25 +15294,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-25T14:18:03+00:00" + "time": "2025-07-10T08:14:14+00:00" }, { "name": "symfony/debug-bundle", - "version": "v6.4.13", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/debug-bundle.git", - "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff" + "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/7bcfaff39e094cc09455201916d016d9b2ae08ff", - "reference": "7bcfaff39e094cc09455201916d016d9b2ae08ff", + "url": "https://api.github.com/repos/symfony/debug-bundle/zipball/21a61c55192d558a6b81cdb12e8c010fc9474fe0", + "reference": "21a61c55192d558a6b81cdb12e8c010fc9474fe0", "shasum": "" }, "require": { @@ -14066,7 +15361,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.13" + "source": "https://github.com/symfony/debug-bundle/tree/v6.4.27" }, "funding": [ { @@ -14077,40 +15372,44 @@ "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-25T14:18:03+00:00" + "time": "2025-10-11T17:35:31+00:00" }, { "name": "symfony/maker-bundle", - "version": "v1.62.1", + "version": "v1.65.0", "source": { "type": "git", "url": "https://github.com/symfony/maker-bundle.git", - "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590" + "reference": "9a0276d7486b29cae641b4a0a85d5e5cc149bff2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/468ff2708200c95ebc0d85d3174b6c6711b8a590", - "reference": "468ff2708200c95ebc0d85d3174b6c6711b8a590", + "url": "https://api.github.com/repos/symfony/maker-bundle/zipball/9a0276d7486b29cae641b4a0a85d5e5cc149bff2", + "reference": "9a0276d7486b29cae641b4a0a85d5e5cc149bff2", "shasum": "" }, "require": { "doctrine/inflector": "^2.0", - "nikic/php-parser": "^4.18|^5.0", + "nikic/php-parser": "^5.0", "php": ">=8.1", - "symfony/config": "^6.4|^7.0", - "symfony/console": "^6.4|^7.0", - "symfony/dependency-injection": "^6.4|^7.0", + "symfony/config": "^6.4|^7.0|^8.0", + "symfony/console": "^6.4|^7.0|^8.0", + "symfony/dependency-injection": "^6.4|^7.0|^8.0", "symfony/deprecation-contracts": "^2.2|^3", - "symfony/filesystem": "^6.4|^7.0", - "symfony/finder": "^6.4|^7.0", - "symfony/framework-bundle": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0" + "symfony/filesystem": "^6.4|^7.0|^8.0", + "symfony/finder": "^6.4|^7.0|^8.0", + "symfony/framework-bundle": "^6.4|^7.0|^8.0", + "symfony/http-kernel": "^6.4|^7.0|^8.0", + "symfony/process": "^6.4|^7.0|^8.0" }, "conflict": { "doctrine/doctrine-bundle": "<2.10", @@ -14118,12 +15417,14 @@ }, "require-dev": { "composer/semver": "^3.0", - "doctrine/doctrine-bundle": "^2.5.0", + "doctrine/doctrine-bundle": "^2.5.0|^3.0.0", "doctrine/orm": "^2.15|^3", - "symfony/http-client": "^6.4|^7.0", - "symfony/phpunit-bridge": "^6.4.1|^7.0", - "symfony/security-core": "^6.4|^7.0", - "symfony/yaml": "^6.4|^7.0", + "doctrine/persistence": "^3.1|^4.0", + "symfony/http-client": "^6.4|^7.0|^8.0", + "symfony/phpunit-bridge": "^6.4.1|^7.0|^8.0", + "symfony/security-core": "^6.4|^7.0|^8.0", + "symfony/security-http": "^6.4|^7.0|^8.0", + "symfony/yaml": "^6.4|^7.0|^8.0", "twig/twig": "^3.0|^4.x-dev" }, "type": "symfony-bundle", @@ -14158,7 +15459,7 @@ ], "support": { "issues": "https://github.com/symfony/maker-bundle/issues", - "source": "https://github.com/symfony/maker-bundle/tree/v1.62.1" + "source": "https://github.com/symfony/maker-bundle/tree/v1.65.0" }, "funding": [ { @@ -14169,25 +15470,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": "2025-01-15T00:21:40+00:00" + "time": "2025-11-24T15:41:51+00:00" }, { "name": "symfony/phpunit-bridge", - "version": "v6.4.23", + "version": "v6.4.26", "source": { "type": "git", "url": "https://github.com/symfony/phpunit-bridge.git", - "reference": "0d26168bf78993b3c49e69e41bea3e7cbecc426c" + "reference": "406aa80401bf960e7a173a3ccf268ae82b6bc93f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/0d26168bf78993b3c49e69e41bea3e7cbecc426c", - "reference": "0d26168bf78993b3c49e69e41bea3e7cbecc426c", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/406aa80401bf960e7a173a3ccf268ae82b6bc93f", + "reference": "406aa80401bf960e7a173a3ccf268ae82b6bc93f", "shasum": "" }, "require": { @@ -14243,7 +15548,7 @@ "testing" ], "support": { - "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.23" + "source": "https://github.com/symfony/phpunit-bridge/tree/v6.4.26" }, "funding": [ { @@ -14254,25 +15559,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": "2025-06-04T07:29:26+00:00" + "time": "2025-09-12T08:37:02+00:00" }, { "name": "symfony/web-profiler-bundle", - "version": "v6.4.19", + "version": "v6.4.27", "source": { "type": "git", "url": "https://github.com/symfony/web-profiler-bundle.git", - "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839" + "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/7d1026a8e950d416cb5148ae88ac23db5d264839", - "reference": "7d1026a8e950d416cb5148ae88ac23db5d264839", + "url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", + "reference": "4c2ab411372e8bd854678cd7c81f1a9bfd6914aa", "shasum": "" }, "require": { @@ -14325,7 +15634,7 @@ "dev" ], "support": { - "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.19" + "source": "https://github.com/symfony/web-profiler-bundle/tree/v6.4.27" }, "funding": [ { @@ -14336,12 +15645,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": "2025-02-14T12:21:59+00:00" + "time": "2025-10-05T13:55:43+00:00" }, { "name": "theofidry/alice-data-fixtures", @@ -14446,16 +15759,16 @@ }, { "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": { @@ -14484,7 +15797,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": [ { @@ -14492,28 +15805,30 @@ "type": "github" } ], - "time": "2024-03-03T12:36:25+00:00" + "time": "2025-11-17T20:03:58+00:00" }, { "name": "vimeo/psalm", - "version": "5.26.1", + "version": "6.13.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0" + "reference": "1e3b7f0a8ab32b23197b91107adc0a7ed8a05b51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/1e3b7f0a8ab32b23197b91107adc0a7ed8a05b51", + "reference": "1e3b7f0a8ab32b23197b91107adc0a7ed8a05b51", "shasum": "" }, "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/parallel": "^2.3", "composer-runtime-api": "^2", "composer/semver": "^1.4 || ^2.0 || ^3.0", "composer/xdebug-handler": "^2.0 || ^3.0", + "danog/advanced-json-rpc": "^3.1", "dnoegel/php-xdg-base-dir": "^0.1.1", "ext-ctype": "*", "ext-dom": "*", @@ -14522,27 +15837,26 @@ "ext-mbstring": "*", "ext-simplexml": "*", "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.1", - "felixfbecker/language-server-protocol": "^1.5.2", + "felixfbecker/language-server-protocol": "^1.5.3", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.17", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "netresearch/jsonmapper": "^5.0", + "nikic/php-parser": "^5.0.0", + "php": "~8.1.31 || ~8.2.27 || ~8.3.16 || ~8.4.3", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" - }, - "conflict": { - "nikic/php-parser": "4.17.0" + "symfony/console": "^6.0 || ^7.0", + "symfony/filesystem": "~6.3.12 || ~6.4.3 || ^7.0.3", + "symfony/polyfill-php84": "^1.31.0" }, "provide": { "psalm/psalm": "self.version" }, "require-dev": { - "amphp/phpunit-util": "^2.0", + "amphp/phpunit-util": "^3", "bamarni/composer-bin-plugin": "^1.4", "brianium/paratest": "^6.9", + "danog/class-finder": "^0.4.8", + "dg/bypass-finals": "^1.5", "ext-curl": "*", "mockery/mockery": "^1.5", "nunomaduro/mock-final-classes": "^1.1", @@ -14550,10 +15864,10 @@ "phpstan/phpdoc-parser": "^1.6", "phpunit/phpunit": "^9.6", "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18", + "psalm/plugin-phpunit": "^0.19", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/process": "^6.0 || ^7.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -14564,6 +15878,7 @@ "psalm-language-server", "psalm-plugin", "psalm-refactor", + "psalm-review", "psalter" ], "type": "project", @@ -14573,7 +15888,9 @@ "dev-2.x": "2.x-dev", "dev-3.x": "3.x-dev", "dev-4.x": "4.x-dev", - "dev-master": "5.x-dev" + "dev-5.x": "5.x-dev", + "dev-6.x": "6.x-dev", + "dev-master": "7.x-dev" } }, "autoload": { @@ -14588,6 +15905,10 @@ "authors": [ { "name": "Matthew Brown" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" } ], "description": "A static analysis tool for finding errors in PHP applications", @@ -14602,20 +15923,20 @@ "issues": "https://github.com/vimeo/psalm/issues", "source": "https://github.com/vimeo/psalm" }, - "time": "2024-09-08T18:53:08+00:00" + "time": "2025-08-06T10:10:28+00:00" }, { "name": "vincentlanglet/twig-cs-fixer", - "version": "3.8.1", + "version": "3.11.0", "source": { "type": "git", "url": "https://github.com/VincentLanglet/Twig-CS-Fixer.git", - "reference": "4e330681d38579a3354bb3dff4b357118baab32c" + "reference": "866af065fd09980b6390ee5c69e45b08053101e8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/4e330681d38579a3354bb3dff4b357118baab32c", - "reference": "4e330681d38579a3354bb3dff4b357118baab32c", + "url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/866af065fd09980b6390ee5c69e45b08053101e8", + "reference": "866af065fd09980b6390ee5c69e45b08053101e8", "shasum": "" }, "require": { @@ -14623,10 +15944,10 @@ "ext-ctype": "*", "ext-json": "*", "php": ">=8.0", - "symfony/console": "^5.4.9 || ^6.4 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.4 || ^7.0", - "symfony/finder": "^5.4 || ^6.4 || ^7.0", - "symfony/string": "^5.4.42 || ^6.4.10 || ~7.0.10 || ^7.1.3", + "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" }, @@ -14644,8 +15965,8 @@ "phpunit/phpunit": "^9.5.26 || ^11.5.18 || ^12.1.3", "rector/rector": "^2.0.0", "shipmonk/composer-dependency-analyser": "^1.6", - "symfony/process": "^5.4 || ^6.4 || ^7.0", - "symfony/twig-bridge": "^5.4 || ^6.4 || ^7.0", + "symfony/process": "^5.4 || ^6.4 || ^7.0 || ^8.0", + "symfony/twig-bridge": "^5.4 || ^6.4 || ^7.0 || ^8.0", "symfony/ux-twig-component": "^2.2.0", "twig/cache-extra": "^3.2" }, @@ -14671,7 +15992,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.8.1" + "source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/3.11.0" }, "funding": [ { @@ -14679,26 +16000,26 @@ "type": "github" } ], - "time": "2025-06-18T07:46:36+00:00" + "time": "2025-11-24T18:13:18+00:00" }, { "name": "weirdan/doctrine-psalm-plugin", - "version": "v2.9.0", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-doctrine.git", - "reference": "3db8e55b2ea15373338d2a3eab71c5f5a31c8b08" + "reference": "8d604c817976e156cd6f1cfab983eadd35b04a2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-doctrine/zipball/3db8e55b2ea15373338d2a3eab71c5f5a31c8b08", - "reference": "3db8e55b2ea15373338d2a3eab71c5f5a31c8b08", + "url": "https://api.github.com/repos/psalm/psalm-plugin-doctrine/zipball/8d604c817976e156cd6f1cfab983eadd35b04a2f", + "reference": "8d604c817976e156cd6f1cfab983eadd35b04a2f", "shasum": "" }, "require": { "composer/semver": "^1.4 || ^2.0 || ^3.0", - "php": "^7.2 || ^8", - "vimeo/psalm": "^4.28|^5.0" + "php": "^8", + "vimeo/psalm": "^6" }, "conflict": { "doctrine/collections": "<1.8", @@ -14755,9 +16076,9 @@ ], "support": { "issues": "https://github.com/psalm/psalm-plugin-doctrine/issues", - "source": "https://github.com/psalm/psalm-plugin-doctrine/tree/v2.9.0" + "source": "https://github.com/psalm/psalm-plugin-doctrine/tree/v2.10.0" }, - "time": "2023-07-15T05:44:30+00:00" + "time": "2025-01-26T11:36:27+00:00" } ], "aliases": [], @@ -14773,5 +16094,5 @@ "ext-iconv": "*" }, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/package-lock.json b/package-lock.json index d959cccb0..f27fef983 100644 --- a/package-lock.json +++ b/package-lock.json @@ -187,6 +187,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1229,6 +1230,7 @@ "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "@fortawesome/fontawesome-common-types": "^0.2.36" }, @@ -1768,6 +1770,7 @@ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -1803,7 +1806,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@reduxjs/toolkit/node_modules/redux-thunk": { "version": "3.1.0", @@ -2518,6 +2522,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz", "integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2817,6 +2822,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001726", "electron-to-chromium": "^1.5.173", @@ -3215,6 +3221,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -3561,6 +3568,7 @@ "devOptional": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -4091,6 +4099,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.17.2" } @@ -5461,6 +5470,7 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5611,6 +5621,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -5664,6 +5675,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", "license": "MIT", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -5756,8 +5768,7 @@ "version": "19.1.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz", "integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", @@ -5833,6 +5844,7 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -6032,6 +6044,7 @@ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.9.2" } @@ -6249,6 +6262,7 @@ "integrity": "sha512-9GUyuksjw70uNpb1MTYWsH9MQHOHY6kwfnkafC24+7aOMZn9+rVMBxRbLvw756mrBFbIsFg6Xw9IkR2Fnn3k+Q==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -6816,6 +6830,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -6871,6 +6886,7 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -6997,6 +7013,7 @@ "resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.0.12.tgz", "integrity": "sha512-Gr40FRnE98FwPJcMwcJgBwP6U7Qxw/VEtDsFdFjvGUTdgI/tTmF7z7dbVo/ajItM54G+Zo9w5BIrUmat6MbuWQ==", "license": "MIT", + "peer": true, "dependencies": { "fdir": "^6.4.6", "lightningcss": "^1.30.1", @@ -7130,6 +7147,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, From f283e945a26dba59846d9520062ef2002e507139 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 8 Dec 2025 08:49:40 +0100 Subject: [PATCH 07/38] 5402: Refactor image build to better use configuration options from underlying images --- .dockerignore | 13 +- infrastructure/Readme.md | 28 +++- infrastructure/display-api-service/Dockerfile | 72 +++++++-- infrastructure/nginx/Dockerfile | 89 +++++++---- infrastructure/nginx/docker-entrypoint.sh | 49 ------ .../nginx/etc/confd/conf.d/default.conf.toml | 7 - .../nginx/etc/confd/conf.d/nginx.conf.toml | 7 - .../etc/confd/templates/default.conf.tmpl | 75 --------- .../nginx/etc/confd/templates/nginx.conf.tmpl | 52 ------- infrastructure/nginx/etc/nginx.conf | 77 ++++++++++ .../nginx/etc/templates/default.conf.template | 145 ++++++++++++++++++ 11 files changed, 365 insertions(+), 249 deletions(-) delete mode 100644 infrastructure/nginx/docker-entrypoint.sh delete mode 100644 infrastructure/nginx/etc/confd/conf.d/default.conf.toml delete mode 100644 infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml delete mode 100644 infrastructure/nginx/etc/confd/templates/default.conf.tmpl delete mode 100644 infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl create mode 100644 infrastructure/nginx/etc/nginx.conf create mode 100644 infrastructure/nginx/etc/templates/default.conf.template diff --git a/.dockerignore b/.dockerignore index 7e18bc03c..fc10ce7dc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,9 +9,7 @@ /infrastructure /public/build /public/fixtures -public/build -public/fixtures -public/media/* +/public/media/* !public/media/thumbnail_other.png !public/media/thumbnail_video.png /scripts @@ -43,17 +41,8 @@ public/media/* xdebug.ini launch.json -###> liip/imagine-bundle ### -/public/media/cache/ -###< liip/imagine-bundle ### - -###> phpstan/phpstan ### -phpstan.neon -###< phpstan/phpstan ### - ###> pentatrion/vite-bundle ### /node_modules/ -/public/build/ ###< pentatrion/vite-bundle ### #> Playwright diff --git a/infrastructure/Readme.md b/infrastructure/Readme.md index 17978bc45..739f3172a 100644 --- a/infrastructure/Readme.md +++ b/infrastructure/Readme.md @@ -1,3 +1,27 @@ -# ITK-development image build +# OS2display image build -This folder contains the infrastructure files for building the `os2display/*` images +This folder contains the infrastructure files for building the `os2display/*` images. + +Two images are built: +- `os2display/display-api-service`: The web (php-fpm) application image +- `os2display/display-api-service-nginx`: The API (nginx) server image + +## Github Actions + +Both images are built automatically on push to the `devolp` branch, and on tag creation. They are tagged with the +same version as the application. + +## Docker Hub + +Images are published to https://hub.docker.com/orgs/os2display + +## Building images locally + +A script is provided to build the images locally: `build-n-push.sh` + +## Build process +Both images uses multistage builds, with the first two stages being identical. And the final stage is optimized for +the specific image. + +This is done because both images requires files from both the `npm` and `composer` build stages. And while having a +shared build stage when building locally is possible, it's not feasible when building on Github Actions. diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index f50de55ff..55bc02687 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,9 +1,35 @@ -######### API backend ######## +######## Clients [Screen|Admin] build ######## +FROM node:24-alpine AS client_app_builder +LABEL maintainer="ITK Dev " + +ARG APP_VERSION="develop" +ARG APP_RELEASE_VERSION="develop" +ARG APP_RELEASE_TIMESTAMP=0 + +ENV APP_CLIENT_PATH=/app +WORKDIR ${APP_CLIENT_PATH} + +# Copy only necessary files for npm install +COPY --from=repository-root package.json package-lock.json vite.config.js ./ + +# Install dependencies +RUN npm ci --no-audit --no-fund + +# Copy source files needed for build +COPY --from=repository-root assets/ ./assets/ +COPY --from=repository-root public/client/ ./public/client/ + +# Build the application with version info +RUN npm run build + + +######### API backend build ######## FROM itkdev/php8.4-fpm:alpine AS api_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" -ENV APP_API_PATH=/var/www/html +ENV APP_CLIENT_PATH=/app \ + APP_API_PATH=/var/www/html USER root @@ -17,28 +43,42 @@ USER deploy # Copy only composer files first for better layer caching COPY --chown=deploy:deploy --from=repository-root composer.json composer.lock symfony.lock ${APP_API_PATH}/ -# Install composer packages first (better image layer caching) +# Pre-install composer packages first (better image layer caching) - application code not present so have to be re-run RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts # Copy application source (needed for build step) COPY --chown=deploy:deploy --from=repository-root ./ ${APP_API_PATH}/ -# Remove frontend apps from api build -RUN rm -rf /assets +# Copy javascript build files. This ensures that vite manifest files are availiable when "composer insatll" +# triggers a "cache:clear" enabling the vite bundle to generate cache configuration files +# @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 +COPY --chown=deploy:deploy --from=client_app_builder ${APP_CLIENT_PATH}/public/build ./public/build -# Install composer packages, which requires a HACK as redis is not available (should be removed later on). -RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative +# Re-run composer install after application code copied to image to complete install +RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative -#### -## Build main application image. -#### - +######## PHP-FPM (API) production image ######## FROM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " -ENV APP_API_PATH=/var/www/html \ - COMPOSER_VERSION=2 +ENV APP_CLIENT_PATH=/app \ + APP_API_PATH=/var/www/html \ + COMPOSER_VERSION=2 \ + + # OpCache + PHP_OPCACHE_ENABLED=1 \ + PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \ + PHP_OPCACHE_MAX_ACCELERATED_FILES=20000 \ + PHP_OPCACHE_MEMORY_CONSUMPTION=256 \ + + # FPM pool + PHP_PM_TYPE="dynamic" \ + PHP_PM_MAX_CHILDREN="24" \ + PHP_PM_MAX_REQUESTS="0" \ + PHP_PM_START_SERVERS="5" \ + PHP_PM_MIN_SPARE_SERVERS="5" \ + PHP_PM_MAX_SPARE_SERVERS="10" USER root @@ -53,9 +93,11 @@ RUN chmod +x /usr/local/bin/docker-entrypoint.sh USER deploy +WORKDIR ${APP_API_PATH} + # Install the api application. -COPY --chown=deploy:deploy --from=api_app_builder ${APP_API_PATH} ${APP_API_PATH} -RUN mkdir -p ${APP_API_PATH}/config/secrets +COPY --chown=deploy:deploy --from=api_app_builder ${APP_API_PATH} . +RUN mkdir -p ./config/secrets WORKDIR ${APP_API_PATH} diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 6754aba58..8379e9cc6 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,66 +1,95 @@ -######## Client [Screen|Admin] build ######## +######## Clients [Screen|Admin] build ######## FROM node:24-alpine AS client_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" ARG APP_RELEASE_VERSION="develop" ARG APP_RELEASE_TIMESTAMP=0 -ENV APP_CLIENT_PATH=/app +ENV APP_CLIENT_PATH=/app WORKDIR ${APP_CLIENT_PATH} # Copy only necessary files for npm install -COPY --from=repository-root package.json package-lock.json vite.config.js ${APP_CLIENT_PATH}/ +COPY --from=repository-root package.json package-lock.json vite.config.js ./ # Install dependencies RUN npm ci --no-audit --no-fund # Copy source files needed for build -COPY --from=repository-root assets/ ${APP_CLIENT_PATH}/assets/ -COPY --from=repository-root public/client/ ${APP_CLIENT_PATH}/public/client/ -COPY --from=repository-root vite.config.js ${APP_CLIENT_PATH}/ +COPY --from=repository-root assets/ ./assets/ -# Build the application +# Build the application with version info RUN npm run build -# Clean up build dependencies and cache -RUN npm cache clean --force && \ - rm -rf node_modules/.cache && \ - rm -rf /root/.npm +######### API backend build ######## +FROM itkdev/php8.4-fpm:alpine AS api_app_builder +LABEL maintainer="ITK Dev " + +ARG APP_VERSION="develop" +ENV APP_CLIENT_PATH=/app \ + APP_API_PATH=/var/www/html + +USER root + +# Add composer in from the official composer image (also alpine). +COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer + +WORKDIR ${APP_API_PATH} + +USER deploy + +# Copy only composer files first for better layer caching +COPY --chown=deploy:deploy --from=repository-root composer.json composer.lock symfony.lock ${APP_API_PATH}/ + +# Pre-install composer packages first (better image layer caching) - application code not present so have to be re-run +RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts + +# Copy application source (needed for build step) +COPY --chown=deploy:deploy --from=repository-root ./ ${APP_API_PATH}/ -######## Nginx build ######## +# Copy javascript build files. This ensures that vite manifest files are availiable when "composer insatll" +# triggers a "cache:clear" enabling the vite bundle to generate cache configuration files +# @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 +COPY --chown=deploy:deploy --from=client_app_builder ${APP_CLIENT_PATH}/public/build ./public/build + +# Re-run composer install after application code copied to image to complete install +RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative + + + +######## Nginx production image ######## FROM nginxinc/nginx-unprivileged:alpine LABEL maintainer="ITK Dev " + +ARG APP_VERSION="develop" +ARG APP_RELEASE_VERSION="develop" +ARG APP_RELEASE_TIMESTAMP=0 ARG UID=101 ARG GID=101 -ENV APP_CLIENT_PATH=/app -ENV APP_API_PATH=/var/www/html +ENV APP_CLIENT_PATH=/app \ + APP_API_PATH=/var/www/html \ + NGINX_PORT=8080 -USER root +WORKDIR ${APP_API_PATH} +# Create directory and copy built client assets RUN mkdir -p ${APP_API_PATH}/public -COPY --from=client_app_builder ${APP_CLIENT_PATH}/public ${APP_API_PATH}/public +COPY --from=api_app_builder --chown=$UID:0 ${APP_API_PATH}/public ./public -WORKDIR ${APP_API_PATH} - -# Copy configuration. -COPY etc /etc/ +# Copy configuration and entrypoint script +COPY --chown=$UID:0 etc /etc/nginx -# Install configuration template handler -ADD https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 /usr/local/bin/confd -RUN chmod +x /usr/local/bin/confd +# Set proper permissions (files are already owned by $UID:0 from COPY --chown) +RUN chmod -R g+w ${APP_API_PATH} -COPY docker-entrypoint.sh / -RUN chmod +x /docker-entrypoint.sh \ - && chown -R $UID:0 ${APP_API_PATH} \ - && chmod -R g+w ${APP_API_PATH} +# Add health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:${NGINX_PORT}/health || exit 1 USER $UID -EXPOSE 8080 - -ENTRYPOINT [ "/docker-entrypoint.sh" ] +EXPOSE ${NGINX_PORT} CMD ["nginx", "-g", "daemon off;"] diff --git a/infrastructure/nginx/docker-entrypoint.sh b/infrastructure/nginx/docker-entrypoint.sh deleted file mode 100644 index 978fa9f4e..000000000 --- a/infrastructure/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -set -eux - -## Run templates with configuration. -/usr/local/bin/confd --onetime --backend env --confdir /etc/confd - -entrypoint_log() { - if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then - echo "$@" - fi -} - -if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then - if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then - entrypoint_log "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration" - - entrypoint_log "$0: Looking for shell scripts in /docker-entrypoint.d/" - find "/docker-entrypoint.d/" -follow -type f -print | sort -V | while read -r f; do - case "$f" in - *.envsh) - if [ -x "$f" ]; then - entrypoint_log "$0: Sourcing $f"; - . "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "$0: Ignoring $f, not executable"; - fi - ;; - *.sh) - if [ -x "$f" ]; then - entrypoint_log "$0: Launching $f"; - "$f" - else - # warn on shell scripts without exec bit - entrypoint_log "$0: Ignoring $f, not executable"; - fi - ;; - *) entrypoint_log "$0: Ignoring $f";; - esac - done - - entrypoint_log "$0: Configuration complete; ready for start up" - else - entrypoint_log "$0: No files found in /docker-entrypoint.d/, skipping configuration" - fi -fi - -exec "$@" diff --git a/infrastructure/nginx/etc/confd/conf.d/default.conf.toml b/infrastructure/nginx/etc/confd/conf.d/default.conf.toml deleted file mode 100644 index 185954f0d..000000000 --- a/infrastructure/nginx/etc/confd/conf.d/default.conf.toml +++ /dev/null @@ -1,7 +0,0 @@ -[template] -src = "default.conf.tmpl" -dest = "/etc/nginx/conf.d/default.conf" -mode = "0644" -keys = [ - "/nginx-config" -] diff --git a/infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml b/infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml deleted file mode 100644 index 7c81a661f..000000000 --- a/infrastructure/nginx/etc/confd/conf.d/nginx.conf.toml +++ /dev/null @@ -1,7 +0,0 @@ -[template] -src = "nginx.conf.tmpl" -dest = "/etc/nginx/nginx.conf" -mode = "0644" -keys = [ - "/nginx-config" -] diff --git a/infrastructure/nginx/etc/confd/templates/default.conf.tmpl b/infrastructure/nginx/etc/confd/templates/default.conf.tmpl deleted file mode 100644 index 7fcd10283..000000000 --- a/infrastructure/nginx/etc/confd/templates/default.conf.tmpl +++ /dev/null @@ -1,75 +0,0 @@ -# @see https://symfony.com/doc/current/setup/web_server_configuration.html -server { - listen 8080; - server_name localhost; - root /var/www/html/public; - - location / { - add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; - - # try to serve file directly, fallback to index.php - try_files $uri /index.php$is_args$args; - } - - # Cache static assets built by Vite under /public/build - location /build/ { - access_log off; - log_not_found off; - - # Serve files directly - try_files $uri =404; - - # Long-term caching for fingerprinted assets - add_header Cache-Control "public, max-age=31536000, immutable"; - expires 1y; - - # Also allow CORS for fonts and similar assets if needed - add_header Access-Control-Allow-Origin "*" always; - - # Do not set X-Robots-Tag for assets - } - - # Screen client online check should just serve static files - location /client/online-check { - index index.html index.htm; - } - - location = /robots.txt { - add_header Content-Type text/plain; - add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; - return 200 "User-agent: *\nDisallow: /\n"; - } - - location ~ ^/index\.php(/|$) { - fastcgi_pass {{ getenv "PHP_FPM_SERVER" "phpfpm" }}:{{ getenv "PHP_FPM_SERVER_PORT" "9000" }}; - fastcgi_split_path_info ^(.+\.php)(/.*)$; - include fastcgi_params; - - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - fastcgi_param DOCUMENT_ROOT $realpath_root; - - internal; - } - - # return 404 for all other php files not matching the front controller - # this prevents access to other php files you don't want to be accessible. - location ~ \.php$ { - return 404; - } - - error_log /var/log/nginx/error.log; - access_log /var/log/nginx/access.log; -} - -server { - listen 8080; - server_name localhost; - root /var/www/html/public; - - error_log off; - access_log off; - - location /stub_status { - stub_status; - } -} diff --git a/infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl b/infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl deleted file mode 100644 index 29d5283af..000000000 --- a/infrastructure/nginx/etc/confd/templates/nginx.conf.tmpl +++ /dev/null @@ -1,52 +0,0 @@ -worker_processes auto; - -error_log /var/log/nginx/error.log warn; -pid /tmp/nginx.pid; - -events { - worker_connections 2048; - multi_accept on; -} - - -http { - open_file_cache max=10000 inactive=5m; - open_file_cache_valid 5m; - open_file_cache_min_uses 5; - open_file_cache_errors off; - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 15 15; - types_hash_max_size 2048; - - server_tokens off; - - client_max_body_size {{ getenv "NGINX_FPM_UPLOAD_MAX" "8M" }}; - - gzip on; - gzip_disable "msie6"; - gzip_vary on; - gzip_proxied any; - gzip_comp_level 6; - gzip_buffers 16 8k; - gzip_http_version 1.0; - gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - set_real_ip_from 172.16.0.0/8; - real_ip_recursive on; - real_ip_header X-Forwarded-For; - - log_format main '$http_x_real_ip - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - error_log /dev/stderr; - access_log /dev/stdout main; - - include /etc/nginx/conf.d/*.conf; -} diff --git a/infrastructure/nginx/etc/nginx.conf b/infrastructure/nginx/etc/nginx.conf new file mode 100644 index 000000000..2fc6396f0 --- /dev/null +++ b/infrastructure/nginx/etc/nginx.conf @@ -0,0 +1,77 @@ +# Note: 'user' directive is not needed in nginx-unprivileged image +worker_processes auto; +worker_rlimit_nofile 65535; + +error_log /dev/stderr notice; +pid /tmp/nginx.pid; + +events { + worker_connections 2048; + use epoll; + multi_accept on; +} + +http { + open_file_cache max=10000 inactive=5m; + open_file_cache_valid 5m; + open_file_cache_min_uses 5; + open_file_cache_errors off; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 15 15; + types_hash_max_size 2048; + + server_tokens off; + + # Compression + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_comp_level 6; + gzip_buffers 16 8k; + gzip_http_version 1.1; + gzip_types + text/plain + text/css + text/xml + text/javascript + application/javascript + application/x-javascript + application/json + application/xml + application/xml+rss + application/rss+xml + application/atom+xml + image/svg+xml + font/truetype + font/opentype + application/vnd.ms-fontobject + application/font-woff + application/font-woff2; + gzip_disable "msie6"; + gzip_proxied any; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always; + + # Rate limiting zones + limit_req_zone $binary_remote_addr zone=php_limit:10m rate=10r/s; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$http_x_real_ip - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + error_log /dev/stderr; + access_log /dev/stdout main; + + include /etc/nginx/conf.d/*.conf; +} diff --git a/infrastructure/nginx/etc/templates/default.conf.template b/infrastructure/nginx/etc/templates/default.conf.template new file mode 100644 index 000000000..1d8f03444 --- /dev/null +++ b/infrastructure/nginx/etc/templates/default.conf.template @@ -0,0 +1,145 @@ +upstream api_backend { + server ${NGINX_FPM_SERVICE}; + keepalive 16; +} + +server { + listen ${NGINX_PORT}; + listen [::]:${NGINX_PORT}; + server_name localhost; + + root /var/www/html/public; + index index.php index.html; + + # Health check endpoint + location /health { + access_log off; + add_header Content-Type text/plain; + return 200 "healthy\n"; + } + + # Upload limits + client_max_body_size ${NGINX_MAX_BODY_SIZE}; + + # Security headers + add_header X-Content-Type-Options "nosniff" always; + add_header X-Frame-Options "DENY" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Real IP from reverse proxy + set_real_ip_from 172.16.0.0/16; + set_real_ip_from ${NGINX_SET_REAL_IP_FROM}; + real_ip_recursive on; + real_ip_header X-Forwarded-For; + + location / { + # Prevent indexing of API routes + add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; + + # try to serve file directly, fallback to index.php + try_files $uri /index.php$is_args$args; + } + + # Cache static assets built by Vite under /public/build + location /build/ { + access_log off; + log_not_found off; + + # Serve files directly + try_files $uri =404; + + # Long-term caching for fingerprinted assets + add_header Cache-Control "public, max-age=31536000, immutable" always; + add_header Access-Control-Allow-Origin "*" always; + add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive" always; + expires 1y; + } + + # Static files with caching + location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + access_log off; + } + + # Screen client online check should just serve static files + location /client/online-check { + index index.html index.htm; + } + + location = /robots.txt { + add_header Content-Type text/plain; + add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; + return 200 "User-agent: *\nDisallow: /\n"; + } + + # Protect sensitive file extensions + location ~* \.(engine|inc|install|make|module|profile|po|sh|sql|tar|gz|bz2|theme|twig|tpl|xtmpl|yml)$ { + deny all; + return 404; + } + + # Protect backup and temporary files + location ~* \.(bak|orig|save|sw[op])$ { + deny all; + return 404; + } + + # Protect dotfiles except .well-known + location ~ /\.(?!well-known) { + deny all; + return 404; + } + + # Protect specific files + location ~ ^/(composer\.(json|lock)|web\.config)$ { + deny all; + return 404; + } + + # PHP-FPM handling + location ~ ^/index\.php(/|$) { + fastcgi_pass api_backend; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include fastcgi_params; + + limit_req zone=php_limit burst=20 nodelay; + + # Increase buffer sizes for large responses + fastcgi_buffers 16 32k; + fastcgi_buffer_size 64k; + fastcgi_busy_buffers_size 64k; + + # Timeout settings + fastcgi_connect_timeout 60s; + fastcgi_send_timeout 60s; + fastcgi_read_timeout 60s; + + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT $realpath_root; + + internal; + } + + # return 404 for all other php files not matching the front controller + # this prevents access to other php files you don't want to be accessible. + location ~ \.php$ { + return 404; + } + + # Send log message to files symlinked to stdout/stderr. + sendfile on; + keepalive_timeout 65; + + # Client buffer settings + client_body_buffer_size 128k; + client_header_buffer_size 1k; + large_client_header_buffers 4 16k; + + gzip on; + gzip_vary on; + gzip_proxied any; + gzip_comp_level 6; + gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; + gzip_disable "msie6"; +} From 9eb1b411a0488701f997767e2ecebc366587d7c3 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 8 Dec 2025 08:50:00 +0100 Subject: [PATCH 08/38] 5402: Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fa3de154..55e641178 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to this project will be documented in this file. - Fix data fetching bug - Refactored screen layout commands. - Moved list components (search and checkboxes) around +- Updated infrastructure and image build for mono-repo ### NB! Prior to 3.x the project was split into separate repositories From a4e710ab52ae4a96bd96c7fe75a7ce44c87d9754 Mon Sep 17 00:00:00 2001 From: turegjorup Date: Mon, 26 Jan 2026 09:23:49 +0100 Subject: [PATCH 09/38] Random --- .env | 4 ++-- infrastructure/display-api-service/Dockerfile | 1 + infrastructure/nginx/Dockerfile | 4 +++- infrastructure/nginx/etc/templates/default.conf.template | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.env b/.env index c8ead6f1d..05d1c0e65 100644 --- a/.env +++ b/.env @@ -19,7 +19,7 @@ ITKDEV_TEMPLATE=symfony-6 ###> symfony/framework-bundle ### APP_ENV=dev -APP_SECRET=22d8a60c047b96413b3337e3ddae3da9 +APP_SECRET=CHANGE_ME TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR ###< symfony/framework-bundle ### @@ -42,7 +42,7 @@ CORS_ALLOW_ORIGIN='^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$' ###> lexik/jwt-authentication-bundle ### JWT_SECRET_KEY=%kernel.project_dir%/config/jwt/private.pem JWT_PUBLIC_KEY=%kernel.project_dir%/config/jwt/public.pem -JWT_PASSPHRASE=APP_JWT_PASSPHRASE +JWT_PASSPHRASE=CHANGE_ME # Default: 1 hour JWT_TOKEN_TTL=3600 # Default: 15 days diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 55bc02687..748268a43 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -64,6 +64,7 @@ LABEL maintainer="ITK Dev " ENV APP_CLIENT_PATH=/app \ APP_API_PATH=/var/www/html \ + APP_ENV=prod \ COMPOSER_VERSION=2 \ # OpCache diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 8379e9cc6..5bf5c00f7 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -70,7 +70,9 @@ ARG GID=101 ENV APP_CLIENT_PATH=/app \ APP_API_PATH=/var/www/html \ - NGINX_PORT=8080 + NGINX_PORT=8080 \ + NGINX_SET_REAL_IP_FROM=172.17.0.0/16 \ + NGINX_MAX_BODY_SIZE=10m WORKDIR ${APP_API_PATH} diff --git a/infrastructure/nginx/etc/templates/default.conf.template b/infrastructure/nginx/etc/templates/default.conf.template index 1d8f03444..52269bea8 100644 --- a/infrastructure/nginx/etc/templates/default.conf.template +++ b/infrastructure/nginx/etc/templates/default.conf.template @@ -27,7 +27,6 @@ server { add_header Referrer-Policy "strict-origin-when-cross-origin" always; # Real IP from reverse proxy - set_real_ip_from 172.16.0.0/16; set_real_ip_from ${NGINX_SET_REAL_IP_FROM}; real_ip_recursive on; real_ip_header X-Forwarded-For; From a483044125581b4c5cb72892bd17750d283e73cd Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:48:33 +0100 Subject: [PATCH 10/38] 5402: Rewrite to publish images to GitHub packages instead of docker hub --- .../docker_build_images_from_tag.yml | 78 ++++++++++++++----- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index 4b441be89..fc80e7ce7 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -5,17 +5,27 @@ on: - "*" # This Action builds to os2display/* using ./infrastructure/* -name: Build docker image (tag) +# @see https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-github-packages + +name: Build docker images (tag) + +env: + REGISTRY: ghcr.io + IMAGE_NAME_MAIN: ${{ github.repository }} + IMAGE_NAME_NGINX: ${{ github.repository }}-nginx jobs: docker: runs-on: ubuntu-latest + # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. + permissions: + contents: read + packages: writes + attestations: write + id-token: write steps: - - name: Login to DockerHub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Checkout repository + uses: actions/checkout@v5 - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -23,39 +33,57 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - # Build api - - name: Docker meta (API) - id: meta-api - uses: docker/metadata-action@v5 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build main + + - name: Docker meta (main) + id: meta-main + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: - images: os2display/display-api-service + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN }} - - name: Build and push (API) - uses: docker/build-push-action@v6 + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: ./infrastructure/display-api-service/ file: ./infrastructure/display-api-service/Dockerfile build-args: | APP_VERSION=${{ github.ref }} push: true - tags: ${{ steps.meta-api.outputs.tags }} - labels: ${{ steps.meta-api.outputs.labels }} + tags: ${{ steps.meta-main.outputs.tags }} + labels: ${{ steps.meta-main.outputs.labels }} provenance: mode=max sbom: true - # Build nginx (depends on api build) - - name: Docker meta (Nginx) + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true + + # Build Nginx (depends on main) + + - name: Docker meta (nginx) id: meta-nginx - uses: docker/metadata-action@v5 + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: - images: os2display/display-api-service-nginx + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX }} - name: Get the tag id: get_tag run: echo ::set-output name=git_tag::$(echo $GITHUB_REF_NAME) - - name: Build and push (Nginx) - uses: docker/build-push-action@v5 + - name: Build and push Docker image + id: push + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: ./infrastructure/nginx/ file: ./infrastructure/nginx/Dockerfile @@ -66,3 +94,11 @@ jobs: labels: ${{ steps.meta-nginx.outputs.labels }} provenance: mode=max sbom: true + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} + subject-digest: ${{ steps.push.outputs.digest }} + push-to-registry: true + From 7e0da14afd24c485a67b8c5a31fd37939e6df030 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:06:05 +0100 Subject: [PATCH 11/38] 6600: Moved commands from taskfile to github actions file --- .github/Taskfile.yml | 46 ---------------------- .github/workflows/github_build_release.yml | 26 ++++++++++-- 2 files changed, 23 insertions(+), 49 deletions(-) delete mode 100644 .github/Taskfile.yml diff --git a/.github/Taskfile.yml b/.github/Taskfile.yml deleted file mode 100644 index 2cb169d48..000000000 --- a/.github/Taskfile.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Task file for GitHub Actions, https://taskfile.dev/ - -version: "3" - -# https://taskfile.dev/usage/#env-files -dotenv: [".env.local", ".env"] - -tasks: - default: - desc: "List all tasks" - cmds: - - task --list-all - silent: true - - build-prod: - desc: "Build application for production" - cmds: - - task setup-network - - task composer-install - - task npm-install - - task install-cleanup - - setup-network: - desc: "Setup docker frontend network" - cmds: - - docker network create frontend - - composer-install: - desc: "Install dependencies with composer." - cmds: - - docker compose run --rm --env APP_ENV=prod phpfpm composer install --no-dev -o --classmap-authoritative - - docker compose run --rm --env APP_ENV=prod phpfpm composer clear-cache - - npm-install: - desc: "Installs node dependencies with npm." - cmds: - - docker compose run --rm node npm install - - docker compose run --rm node npm run build - - install-cleanup: - desc: "Cleanup after install" - cmds: - - rm -rf infrastructure - - rm -rf fixtures - - rm -rf tests - - rm -rf node_modules diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 810ab96e3..559ac29a0 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -1,3 +1,5 @@ +# This workflow builds a GitHub release on tag creation. + on: push: tags: @@ -21,10 +23,28 @@ jobs: - name: Install Task task runner uses: go-task/setup-task@v1 - - name: Install, Build, Cleanup + - name: Setup docker network + run: | + docker network create frontend + + - name: Install dependencies with composer + run: | + docker compose run --rm --env APP_ENV=prod phpfpm composer install --no-dev -o --classmap-authoritative + docker compose run --rm --env APP_ENV=prod phpfpm composer clear-cache + + - name: Installs node dependencies with npm + run: | + docker compose run --rm node npm install + docker compose run --rm node npm run build + + - name: Cleanup after install run: | - task --taskfile=.github/Taskfile.yaml build-prod - + rm -rf docs + rm -rf infrastructure + rm -rf fixtures + rm -rf tests + rm -rf node_modules + - name: Make assets dir run: | mkdir -p ../assets From 6b67736d704cac79d02fe5890a642a78fa72d0b4 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 11:44:02 +0100 Subject: [PATCH 12/38] 6601: Updated composer lock file --- composer.lock | 1824 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 1428 insertions(+), 396 deletions(-) diff --git a/composer.lock b/composer.lock index d6fd19db3..ff2717b45 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1bd6fd456477d1e03a03bb4359ad3e77", + "content-hash": "567a746ddcb5a440c396fc6ea9cfa7ac", "packages": [ { "name": "api-platform/core", @@ -1046,29 +1046,29 @@ }, { "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", @@ -5722,16 +5722,16 @@ }, { "name": "symfony/cache", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/cache.git", - "reference": "a1b306757c34b96fe97c0c586f50dceed05c7adb" + "reference": "5b088fa41eb9568748dc255c45e4054c387ba73b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/cache/zipball/a1b306757c34b96fe97c0c586f50dceed05c7adb", - "reference": "a1b306757c34b96fe97c0c586f50dceed05c7adb", + "url": "https://api.github.com/repos/symfony/cache/zipball/5b088fa41eb9568748dc255c45e4054c387ba73b", + "reference": "5b088fa41eb9568748dc255c45e4054c387ba73b", "shasum": "" }, "require": { @@ -5798,7 +5798,7 @@ "psr6" ], "support": { - "source": "https://github.com/symfony/cache/tree/v6.4.31" + "source": "https://github.com/symfony/cache/tree/v6.4.33" }, "funding": [ { @@ -5818,7 +5818,7 @@ "type": "tidelift" } ], - "time": "2025-12-27T18:26:25+00:00" + "time": "2026-01-27T15:05:20+00:00" }, { "name": "symfony/cache-contracts", @@ -5976,16 +5976,16 @@ }, { "name": "symfony/config", - "version": "v6.4.28", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62" + "reference": "d445badf0ad2c2a492e38c0378c39997a56ef97b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/15947c18ef3ddb0b2f4ec936b9e90e2520979f62", - "reference": "15947c18ef3ddb0b2f4ec936b9e90e2520979f62", + "url": "https://api.github.com/repos/symfony/config/zipball/d445badf0ad2c2a492e38c0378c39997a56ef97b", + "reference": "d445badf0ad2c2a492e38c0378c39997a56ef97b", "shasum": "" }, "require": { @@ -6031,7 +6031,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.32" }, "funding": [ { @@ -6051,20 +6051,20 @@ "type": "tidelift" } ], - "time": "2025-11-01T19:52:02+00:00" + "time": "2026-01-13T08:40:30+00:00" }, { "name": "symfony/console", - "version": "v6.4.31", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997" + "reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f9f8a889f54c264f9abac3fc0f7a371ffca51997", - "reference": "f9f8a889f54c264f9abac3fc0f7a371ffca51997", + "url": "https://api.github.com/repos/symfony/console/zipball/0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3", + "reference": "0bc2199c6c1f05276b05956f1ddc63f6d7eb5fc3", "shasum": "" }, "require": { @@ -6129,7 +6129,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.31" + "source": "https://github.com/symfony/console/tree/v6.4.32" }, "funding": [ { @@ -6149,20 +6149,20 @@ "type": "tidelift" } ], - "time": "2025-12-22T08:30:34+00:00" + "time": "2026-01-13T08:45:59+00:00" }, { "name": "symfony/dependency-injection", - "version": "v6.4.31", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/dependency-injection.git", - "reference": "10058832a74a33648870aa2057e3fdc8796a6566" + "reference": "b17882e933c4c606620247b6708ab53aa3b88753" }, "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/b17882e933c4c606620247b6708ab53aa3b88753", + "reference": "b17882e933c4c606620247b6708ab53aa3b88753", "shasum": "" }, "require": { @@ -6214,7 +6214,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.32" }, "funding": [ { @@ -6234,7 +6234,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T13:34:50+00:00" + "time": "2026-01-23T10:54:33+00:00" }, { "name": "symfony/deprecation-contracts", @@ -6566,16 +6566,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 +6621,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 +6641,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 +6705,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 +6725,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 +6805,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 +6849,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,7 +6869,7 @@ "type": "tidelift" } ], - "time": "2025-11-09T10:02:06+00:00" + "time": "2026-01-04T11:52:13+00:00" }, { "name": "symfony/filesystem", @@ -6943,16 +6943,16 @@ }, { "name": "symfony/finder", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b" + "reference": "24965ca011dac87431729640feef8bcf7b5523e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/5547f2e1f0ca8e2e7abe490156b62da778cfbe2b", - "reference": "5547f2e1f0ca8e2e7abe490156b62da778cfbe2b", + "url": "https://api.github.com/repos/symfony/finder/zipball/24965ca011dac87431729640feef8bcf7b5523e0", + "reference": "24965ca011dac87431729640feef8bcf7b5523e0", "shasum": "" }, "require": { @@ -6987,7 +6987,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.33" }, "funding": [ { @@ -7007,7 +7007,7 @@ "type": "tidelift" } ], - "time": "2025-12-11T14:52:17+00:00" + "time": "2026-01-26T13:03:48+00:00" }, { "name": "symfony/flex", @@ -7084,16 +7084,16 @@ }, { "name": "symfony/framework-bundle", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/framework-bundle.git", - "reference": "0ab60c05570b9e2bfab92b9944b938b8ffb5ba96" + "reference": "9ef2d0b63b9e855ba351e770a603d89699115801" }, "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/9ef2d0b63b9e855ba351e770a603d89699115801", + "reference": "9ef2d0b63b9e855ba351e770a603d89699115801", "shasum": "" }, "require": { @@ -7213,7 +7213,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.33" }, "funding": [ { @@ -7233,7 +7233,7 @@ "type": "tidelift" } ], - "time": "2025-12-23T14:16:13+00:00" + "time": "2026-01-26T14:46:41+00:00" }, { "name": "symfony/http-client", @@ -7413,16 +7413,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a35ee6f47e4775179704d7877a8b0da3cb09241a" + "reference": "f1a490cc9d595ba7ebe684220e625d1e472ad278" }, "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/f1a490cc9d595ba7ebe684220e625d1e472ad278", + "reference": "f1a490cc9d595ba7ebe684220e625d1e472ad278", "shasum": "" }, "require": { @@ -7470,7 +7470,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.33" }, "funding": [ { @@ -7490,20 +7490,20 @@ "type": "tidelift" } ], - "time": "2025-12-17T10:10:57+00:00" + "time": "2026-01-27T15:04:55+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.4.31", + "version": "v6.4.33", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "16b0d46d8e11f480345c15b229cfc827a8a0f731" + "reference": "73fa5c999d7f741ca544a97d3c791cc97890ae4d" }, "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/73fa5c999d7f741ca544a97d3c791cc97890ae4d", + "reference": "73fa5c999d7f741ca544a97d3c791cc97890ae4d", "shasum": "" }, "require": { @@ -7588,7 +7588,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.33" }, "funding": [ { @@ -7608,20 +7608,20 @@ "type": "tidelift" } ], - "time": "2025-12-31T08:27:27+00:00" + "time": "2026-01-28T10:02:13+00:00" }, { "name": "symfony/mime", - "version": "v6.4.30", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "69aeef5d2692bb7c18ce133b09f67b27260b7acf" + "reference": "7409686879ca36c09fc970a5fa8ff6e93504dba4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/69aeef5d2692bb7c18ce133b09f67b27260b7acf", - "reference": "69aeef5d2692bb7c18ce133b09f67b27260b7acf", + "url": "https://api.github.com/repos/symfony/mime/zipball/7409686879ca36c09fc970a5fa8ff6e93504dba4", + "reference": "7409686879ca36c09fc970a5fa8ff6e93504dba4", "shasum": "" }, "require": { @@ -7677,7 +7677,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.4.30" + "source": "https://github.com/symfony/mime/tree/v6.4.32" }, "funding": [ { @@ -7697,7 +7697,7 @@ "type": "tidelift" } ], - "time": "2025-11-16T09:57:53+00:00" + "time": "2026-01-04T11:53:14+00:00" }, { "name": "symfony/monolog-bridge", @@ -8825,16 +8825,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 +8866,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,7 +8886,7 @@ "type": "tidelift" } ], - "time": "2025-12-15T19:26:35+00:00" + "time": "2026-01-23T16:02:12+00:00" }, { "name": "symfony/property-access", @@ -9132,16 +9132,16 @@ }, { "name": "symfony/routing", - "version": "v6.4.30", + "version": "v6.4.32", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "ea50a13c2711eebcbb66b38ef6382e62e3262859" + "reference": "0dc6253e864e71b486e8ba4970a56ab849106ebe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/ea50a13c2711eebcbb66b38ef6382e62e3262859", - "reference": "ea50a13c2711eebcbb66b38ef6382e62e3262859", + "url": "https://api.github.com/repos/symfony/routing/zipball/0dc6253e864e71b486e8ba4970a56ab849106ebe", + "reference": "0dc6253e864e71b486e8ba4970a56ab849106ebe", "shasum": "" }, "require": { @@ -9195,7 +9195,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.4.30" + "source": "https://github.com/symfony/routing/tree/v6.4.32" }, "funding": [ { @@ -9215,7 +9215,7 @@ "type": "tidelift" } ], - "time": "2025-11-22T09:51:35+00:00" + "time": "2026-01-12T08:31:19+00:00" }, { "name": "symfony/runtime", @@ -10478,16 +10478,16 @@ }, { "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 +10542,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 +10562,7 @@ "type": "tidelift" } ], - "time": "2025-09-25T15:37:27+00:00" + "time": "2026-01-01T13:34:06+00:00" }, { "name": "symfony/var-exporter", @@ -11113,38 +11113,36 @@ "packages-dev": [ { "name": "amphp/amp", - "version": "v2.6.5", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/amphp/amp.git", - "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207" + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/amp/zipball/d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", - "reference": "d7dda98dae26e56f3f6fcfbf1c1f819c9a993207", + "url": "https://api.github.com/repos/amphp/amp/zipball/fa0ab33a6f47a82929c38d03ca47ebb71086a93f", + "reference": "fa0ab33a6f47a82929c38d03ca47ebb71086a93f", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1", - "ext-json": "*", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^7 | ^8 | ^9", - "react/promise": "^2", - "vimeo/psalm": "^3.12" + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23.1" }, "type": "library", "autoload": { "files": [ - "lib/functions.php", - "lib/Internal/functions.php" + "src/functions.php", + "src/Future/functions.php", + "src/Internal/functions.php" ], "psr-4": { - "Amp\\": "lib" + "Amp\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11152,10 +11150,6 @@ "MIT" ], "authors": [ - { - "name": "Daniel Lowrey", - "email": "rdlowrey@php.net" - }, { "name": "Aaron Piotrowski", "email": "aaron@trowski.com" @@ -11167,6 +11161,10 @@ { "name": "Niklas Keller", "email": "me@kelunik.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" } ], "description": "A non-blocking concurrency framework for PHP applications.", @@ -11183,9 +11181,8 @@ "promise" ], "support": { - "irc": "irc://irc.freenode.org/amphp", "issues": "https://github.com/amphp/amp/issues", - "source": "https://github.com/amphp/amp/tree/v2.6.5" + "source": "https://github.com/amphp/amp/tree/v3.1.1" }, "funding": [ { @@ -11193,41 +11190,45 @@ "type": "github" } ], - "time": "2025-09-03T19:41:28+00:00" + "time": "2025-08-27T21:42:00+00:00" }, { "name": "amphp/byte-stream", - "version": "v1.8.2", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/amphp/byte-stream.git", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", - "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/55a6bd071aec26fa2a3e002618c20c35e3df1b46", + "reference": "55a6bd071aec26fa2a3e002618c20c35e3df1b46", "shasum": "" }, "require": { - "amphp/amp": "^2", - "php": ">=7.1" + "amphp/amp": "^3", + "amphp/parser": "^1.1", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2.3" }, "require-dev": { - "amphp/php-cs-fixer-config": "dev-master", - "amphp/phpunit-util": "^1.4", - "friendsofphp/php-cs-fixer": "^2.3", - "jetbrains/phpstorm-stubs": "^2019.3", - "phpunit/phpunit": "^6 || ^7 || ^8", - "psalm/phar": "^3.11.4" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.22.1" }, "type": "library", "autoload": { "files": [ - "lib/functions.php" + "src/functions.php", + "src/Internal/functions.php" ], "psr-4": { - "Amp\\ByteStream\\": "lib" + "Amp\\ByteStream\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11256,7 +11257,7 @@ ], "support": { "issues": "https://github.com/amphp/byte-stream/issues", - "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + "source": "https://github.com/amphp/byte-stream/tree/v2.1.2" }, "funding": [ { @@ -11264,94 +11265,112 @@ "type": "github" } ], - "time": "2024-04-13T18:00:56+00:00" + "time": "2025-03-16T17:10:27+00:00" }, { - "name": "dnoegel/php-xdg-base-dir", - "version": "v0.1.1", + "name": "amphp/cache", + "version": "v2.0.1", "source": { "type": "git", - "url": "https://github.com/dnoegel/php-xdg-base-dir.git", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + "url": "https://github.com/amphp/cache.git", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", - "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "url": "https://api.github.com/repos/amphp/cache/zipball/46912e387e6aa94933b61ea1ead9cf7540b7797c", + "reference": "46912e387e6aa94933b61ea1ead9cf7540b7797c", "shasum": "" }, "require": { - "php": ">=5.3.2" + "amphp/amp": "^3", + "amphp/serialization": "^1", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" }, "type": "library", "autoload": { "psr-4": { - "XdgBaseDir\\": "src/" + "Amp\\Cache\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "implementation of xdg base directory specification for php", + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + } + ], + "description": "A fiber-aware cache API based on Amp and Revolt.", + "homepage": "https://amphp.org/cache", "support": { - "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", - "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + "issues": "https://github.com/amphp/cache/issues", + "source": "https://github.com/amphp/cache/tree/v2.0.1" }, - "time": "2019-12-04T15:06:13+00:00" + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:38:06+00:00" }, { - "name": "doctrine/data-fixtures", - "version": "1.8.2", + "name": "amphp/dns", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/doctrine/data-fixtures.git", - "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5" + "url": "https://github.com/amphp/dns.git", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/6fb221da56dae2011b33d47508e3b8aeb1d91db5", - "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5", + "url": "https://api.github.com/repos/amphp/dns/zipball/78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", + "reference": "78eb3db5fc69bf2fc0cb503c4fcba667bc223c71", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1.0", - "doctrine/persistence": "^2.0 || ^3.0", - "php": "^7.4 || ^8.0", - "symfony/polyfill-php80": "^1" - }, - "conflict": { - "doctrine/dbal": "<3.5 || >=5", - "doctrine/orm": "<2.14 || >=4", - "doctrine/phpcr-odm": "<1.3.0" + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/process": "^2", + "daverandom/libdns": "^2.0.2", + "ext-filter": "*", + "ext-json": "*", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" }, "require-dev": { - "doctrine/annotations": "^1.12 || ^2", - "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": "*", - "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" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", - "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", - "doctrine/orm": "For loading ORM fixtures", - "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" }, "type": "library", "autoload": { + "files": [ + "src/functions.php" + ], "psr-4": { - "Doctrine\\Common\\DataFixtures\\": "src" + "Amp\\Dns\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11360,91 +11379,91 @@ ], "authors": [ { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" + "name": "Chris Wright", + "email": "addr@daverandom.com" + }, + { + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" } ], - "description": "Data Fixtures for all Doctrine Object Managers", - "homepage": "https://www.doctrine-project.org", + "description": "Async DNS resolution for Amp.", + "homepage": "https://github.com/amphp/dns", "keywords": [ - "database" + "amp", + "amphp", + "async", + "client", + "dns", + "resolve" ], "support": { - "issues": "https://github.com/doctrine/data-fixtures/issues", - "source": "https://github.com/doctrine/data-fixtures/tree/1.8.2" + "issues": "https://github.com/amphp/dns/issues", + "source": "https://github.com/amphp/dns/tree/v2.4.0" }, "funding": [ { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", - "type": "tidelift" + "url": "https://github.com/amphp", + "type": "github" } ], - "time": "2025-06-10T07:00:05+00:00" + "time": "2025-01-19T15:43:40+00:00" }, { - "name": "ergebnis/composer-normalize", - "version": "2.48.2", + "name": "amphp/parallel", + "version": "v2.3.3", "source": { "type": "git", - "url": "https://github.com/ergebnis/composer-normalize.git", - "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" + "url": "https://github.com/amphp/parallel.git", + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", - "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "url": "https://api.github.com/repos/amphp/parallel/zipball/296b521137a54d3a02425b464e5aee4c93db2c60", + "reference": "296b521137a54d3a02425b464e5aee4c93db2c60", "shasum": "" }, "require": { - "composer-plugin-api": "^2.0.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 || ^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" + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/cache": "^2", + "amphp/parser": "^1", + "amphp/pipeline": "^1", + "amphp/process": "^2", + "amphp/serialization": "^1", + "amphp/socket": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1" }, "require-dev": { - "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", - "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" - } + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" }, + "type": "library", "autoload": { + "files": [ + "src/Context/functions.php", + "src/Context/Internal/functions.php", + "src/Ipc/functions.php", + "src/Worker/functions.php" + ], "psr-4": { - "Ergebnis\\Composer\\Normalize\\": "src/" + "Amp\\Parallel\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11453,74 +11472,65 @@ ], "authors": [ { - "name": "Andreas Möller", - "email": "am@localheinz.com", - "homepage": "https://localheinz.com" + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" } ], - "description": "Provides a composer plugin for normalizing composer.json.", - "homepage": "https://github.com/ergebnis/composer-normalize", + "description": "Parallel processing component for Amp.", + "homepage": "https://github.com/amphp/parallel", "keywords": [ - "composer", - "normalize", - "normalizer", - "plugin" + "async", + "asynchronous", + "concurrent", + "multi-processing", + "multi-threading" ], "support": { - "issues": "https://github.com/ergebnis/composer-normalize/issues", - "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md", - "source": "https://github.com/ergebnis/composer-normalize" + "issues": "https://github.com/amphp/parallel/issues", + "source": "https://github.com/amphp/parallel/tree/v2.3.3" }, - "time": "2025-09-06T11:42:34+00:00" + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-11-15T06:23:42+00:00" }, { - "name": "ergebnis/json", - "version": "1.6.0", + "name": "amphp/parser", + "version": "v1.1.1", "source": { "type": "git", - "url": "https://github.com/ergebnis/json.git", - "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1" + "url": "https://github.com/amphp/parser.git", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/json/zipball/7b56d2b5d9e897e75b43e2e753075a0904c921b1", - "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1", + "url": "https://api.github.com/repos/amphp/parser/zipball/3cf1f8b32a0171d4b1bed93d25617637a77cded7", + "reference": "3cf1f8b32a0171d4b1bed93d25617637a77cded7", "shasum": "" }, "require": { - "ext-json": "*", - "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0" + "php": ">=7.4" }, "require-dev": { - "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", - "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" + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" }, "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.7-dev" - }, - "composer-normalize": { - "indent-size": 2, - "indent-style": "space" - } - }, "autoload": { "psr-4": { - "Ergebnis\\Json\\": "src/" + "Amp\\Parser\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -11529,7 +11539,746 @@ ], "authors": [ { - "name": "Andreas Möller", + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A generator parser to make streaming parsers simple.", + "homepage": "https://github.com/amphp/parser", + "keywords": [ + "async", + "non-blocking", + "parser", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/parser/issues", + "source": "https://github.com/amphp/parser/tree/v1.1.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-03-21T19:16:53+00:00" + }, + { + "name": "amphp/pipeline", + "version": "v1.2.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/pipeline.git", + "reference": "7b52598c2e9105ebcddf247fc523161581930367" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/pipeline/zipball/7b52598c2e9105ebcddf247fc523161581930367", + "reference": "7b52598c2e9105ebcddf247fc523161581930367", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "php": ">=8.1", + "revolt/event-loop": "^1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.18" + }, + "type": "library", + "autoload": { + "psr-4": { + "Amp\\Pipeline\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Asynchronous iterators and operators.", + "homepage": "https://amphp.org/pipeline", + "keywords": [ + "amp", + "amphp", + "async", + "io", + "iterator", + "non-blocking" + ], + "support": { + "issues": "https://github.com/amphp/pipeline/issues", + "source": "https://github.com/amphp/pipeline/tree/v1.2.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2025-03-16T16:33:53+00:00" + }, + { + "name": "amphp/process", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/amphp/process.git", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/process/zipball/52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "reference": "52e08c09dec7511d5fbc1fb00d3e4e79fc77d58d", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/sync": "^2", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.4" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Process\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A fiber-aware process manager based on Amp and Revolt.", + "homepage": "https://amphp.org/process", + "support": { + "issues": "https://github.com/amphp/process/issues", + "source": "https://github.com/amphp/process/tree/v2.0.3" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-19T03:13:44+00:00" + }, + { + "name": "amphp/serialization", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/serialization.git", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1", + "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "dev-master", + "phpunit/phpunit": "^9 || ^8 || ^7" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Serialization\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Serialization tools for IPC and data storage in PHP.", + "homepage": "https://github.com/amphp/serialization", + "keywords": [ + "async", + "asynchronous", + "serialization", + "serialize" + ], + "support": { + "issues": "https://github.com/amphp/serialization/issues", + "source": "https://github.com/amphp/serialization/tree/master" + }, + "time": "2020-03-25T21:39:07+00:00" + }, + { + "name": "amphp/socket", + "version": "v2.3.1", + "source": { + "type": "git", + "url": "https://github.com/amphp/socket.git", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/socket/zipball/58e0422221825b79681b72c50c47a930be7bf1e1", + "reference": "58e0422221825b79681b72c50c47a930be7bf1e1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/dns": "^2", + "ext-openssl": "*", + "kelunik/certificate": "^1.1", + "league/uri": "^6.5 | ^7", + "league/uri-interfaces": "^2.3 | ^7", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "amphp/process": "^2", + "phpunit/phpunit": "^9", + "psalm/phar": "5.20" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php", + "src/Internal/functions.php", + "src/SocketAddress/functions.php" + ], + "psr-4": { + "Amp\\Socket\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniel Lowrey", + "email": "rdlowrey@gmail.com" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Non-blocking socket connection / server implementations based on Amp and Revolt.", + "homepage": "https://github.com/amphp/socket", + "keywords": [ + "amp", + "async", + "encryption", + "non-blocking", + "sockets", + "tcp", + "tls" + ], + "support": { + "issues": "https://github.com/amphp/socket/issues", + "source": "https://github.com/amphp/socket/tree/v2.3.1" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-04-21T14:33:03+00:00" + }, + { + "name": "amphp/sync", + "version": "v2.3.0", + "source": { + "type": "git", + "url": "https://github.com/amphp/sync.git", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/amphp/sync/zipball/217097b785130d77cfcc58ff583cf26cd1770bf1", + "reference": "217097b785130d77cfcc58ff583cf26cd1770bf1", + "shasum": "" + }, + "require": { + "amphp/amp": "^3", + "amphp/pipeline": "^1", + "amphp/serialization": "^1", + "php": ">=8.1", + "revolt/event-loop": "^1 || ^0.2" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "amphp/phpunit-util": "^3", + "phpunit/phpunit": "^9", + "psalm/phar": "5.23" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Amp\\Sync\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + }, + { + "name": "Stephen Coakley", + "email": "me@stephencoakley.com" + } + ], + "description": "Non-blocking synchronization primitives for PHP based on Amp and Revolt.", + "homepage": "https://github.com/amphp/sync", + "keywords": [ + "async", + "asynchronous", + "mutex", + "semaphore", + "synchronization" + ], + "support": { + "issues": "https://github.com/amphp/sync/issues", + "source": "https://github.com/amphp/sync/tree/v2.3.0" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } + ], + "time": "2024-08-03T19:31:26+00:00" + }, + { + "name": "danog/advanced-json-rpc", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/danog/php-advanced-json-rpc.git", + "reference": "ae703ea7b4811797a10590b6078de05b3b33dd91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/danog/php-advanced-json-rpc/zipball/ae703ea7b4811797a10590b6078de05b3b33dd91", + "reference": "ae703ea7b4811797a10590b6078de05b3b33dd91", + "shasum": "" + }, + "require": { + "netresearch/jsonmapper": "^5", + "php": ">=8.1", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0 || ^6" + }, + "replace": { + "felixfbecker/php-advanced-json-rpc": "^3" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Felix Becker", + "email": "felix.b@outlook.com" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" + } + ], + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/danog/php-advanced-json-rpc/issues", + "source": "https://github.com/danog/php-advanced-json-rpc/tree/v3.2.3" + }, + "time": "2026-01-12T21:07:10+00:00" + }, + { + "name": "daverandom/libdns", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/DaveRandom/LibDNS.git", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "reference": "b84c94e8fe6b7ee4aecfe121bfe3b6177d303c8a", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "Required for IDN support" + }, + "type": "library", + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "LibDNS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "DNS protocol implementation written in pure PHP", + "keywords": [ + "dns" + ], + "support": { + "issues": "https://github.com/DaveRandom/LibDNS/issues", + "source": "https://github.com/DaveRandom/LibDNS/tree/v2.1.0" + }, + "time": "2024-04-12T12:12:48+00:00" + }, + { + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "XdgBaseDir\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" + }, + { + "name": "doctrine/data-fixtures", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "6fb221da56dae2011b33d47508e3b8aeb1d91db5" + }, + "dist": { + "type": "zip", + "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", + "symfony/polyfill-php80": "^1" + }, + "conflict": { + "doctrine/dbal": "<3.5 || >=5", + "doctrine/orm": "<2.14 || >=4", + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "doctrine/annotations": "^1.12 || ^2", + "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": "*", + "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" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "database" + ], + "support": { + "issues": "https://github.com/doctrine/data-fixtures/issues", + "source": "https://github.com/doctrine/data-fixtures/tree/1.8.2" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", + "type": "tidelift" + } + ], + "time": "2025-06-10T07:00:05+00:00" + }, + { + "name": "ergebnis/composer-normalize", + "version": "2.48.2", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/composer-normalize.git", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "reference": "86dc9731b8320f49e9be9ad6d8e4de9b8b0e9b8b", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.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 || ^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.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", + "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" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\Composer\\Normalize\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com", + "homepage": "https://localheinz.com" + } + ], + "description": "Provides a composer plugin for normalizing composer.json.", + "homepage": "https://github.com/ergebnis/composer-normalize", + "keywords": [ + "composer", + "normalize", + "normalizer", + "plugin" + ], + "support": { + "issues": "https://github.com/ergebnis/composer-normalize/issues", + "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" + }, + { + "name": "ergebnis/json", + "version": "1.6.0", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/json.git", + "reference": "7b56d2b5d9e897e75b43e2e753075a0904c921b1" + }, + "dist": { + "type": "zip", + "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 || ~8.5.0" + }, + "require-dev": { + "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", + "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" + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\Json\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", "email": "am@localheinz.com", "homepage": "https://localheinz.com" } @@ -11916,51 +12665,6 @@ }, "time": "2024-11-21T13:46:39+00:00" }, - { - "name": "felixfbecker/advanced-json-rpc", - "version": "v3.2.1", - "source": { - "type": "git", - "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", - "shasum": "" - }, - "require": { - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0", - "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.0 || ^8.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "AdvancedJsonRpc\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Felix Becker", - "email": "felix.b@outlook.com" - } - ], - "description": "A more advanced JSONRPC implementation", - "support": { - "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", - "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" - }, - "time": "2021-06-11T22:34:44+00:00" - }, { "name": "felixfbecker/language-server-protocol", "version": "v1.5.3", @@ -12091,6 +12795,246 @@ }, "time": "2023-12-03T23:53:29+00:00" }, + { + "name": "kelunik/certificate", + "version": "v1.1.3", + "source": { + "type": "git", + "url": "https://github.com/kelunik/certificate.git", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kelunik/certificate/zipball/7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "reference": "7e00d498c264d5eb4f78c69f41c8bd6719c0199e", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=7.0" + }, + "require-dev": { + "amphp/php-cs-fixer-config": "^2", + "phpunit/phpunit": "^6 | 7 | ^8 | ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Kelunik\\Certificate\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Access certificate details and transform between different formats.", + "keywords": [ + "DER", + "certificate", + "certificates", + "openssl", + "pem", + "x509" + ], + "support": { + "issues": "https://github.com/kelunik/certificate/issues", + "source": "https://github.com/kelunik/certificate/tree/v1.1.3" + }, + "time": "2023-02-03T21:26:53+00:00" + }, + { + "name": "league/uri", + "version": "7.8.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "4436c6ec8d458e4244448b069cc572d088230b76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/4436c6ec8d458e4244448b069cc572d088230b76", + "reference": "4436c6ec8d458e4244448b069cc572d088230b76", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.8", + "php": "^8.1", + "psr/http-factory": "^1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-dom": "to convert the URI into an HTML anchor tag", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "ext-uri": "to use the PHP native URI class", + "jeremykendall/php-domain-parser": "to further parse the URI host and resolve its Public Suffix and Top Level Domain", + "league/uri-components": "to provide additional tools to manipulate URI objects components", + "league/uri-polyfill": "to backport the PHP URI extension for older versions of PHP", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "URN", + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc2141", + "rfc3986", + "rfc3987", + "rfc6570", + "rfc8141", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.8.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-01-14T17:24:56+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.8.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "reference": "c5c5cd056110fc8afaba29fa6b72a43ced42acd4", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "rowbot/url": "to handle URLs using the WHATWG URL Living Standard specification", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common tools for parsing and resolving RFC3987/RFC3986 URI", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.8.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2026-01-15T06:54:53+00:00" + }, { "name": "localheinz/diff", "version": "1.3.0", @@ -12303,16 +13247,16 @@ }, { "name": "netresearch/jsonmapper", - "version": "v4.5.0", + "version": "v5.0.0", "source": { "type": "git", "url": "https://github.com/cweiske/jsonmapper.git", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5" + "reference": "8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8e76efb98ee8b6afc54687045e1b8dba55ac76e5", - "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c", + "reference": "8c64d8d444a5d764c641ebe97e0e3bc72b25bf6c", "shasum": "" }, "require": { @@ -12348,36 +13292,43 @@ "support": { "email": "cweiske@cweiske.de", "issues": "https://github.com/cweiske/jsonmapper/issues", - "source": "https://github.com/cweiske/jsonmapper/tree/v4.5.0" + "source": "https://github.com/cweiske/jsonmapper/tree/v5.0.0" }, - "time": "2024-09-08T10:13:13+00:00" + "time": "2024-09-08T10:20:00+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.5", + "version": "v5.7.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837" + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", - "reference": "51bd93cc741b7fc3d63d20b6bdcd99fdaa359837", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" ], "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, "autoload": { "psr-4": { "PhpParser\\": "lib/PhpParser" @@ -12399,9 +13350,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" }, - "time": "2025-12-06T11:45:25+00:00" + "time": "2025-12-06T11:56:16+00:00" }, { "name": "phar-io/manifest", @@ -13006,34 +13957,35 @@ }, { "name": "psalm/plugin-symfony", - "version": "v5.2.6", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-symfony.git", - "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742" + "reference": "df874ff48ae3b1833ea17fba7c21b31a4d682614" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/1638f172b4ae5f283ee6b1b58fff3e44aa628742", - "reference": "1638f172b4ae5f283ee6b1b58fff3e44aa628742", + "url": "https://api.github.com/repos/psalm/psalm-plugin-symfony/zipball/df874ff48ae3b1833ea17fba7c21b31a4d682614", + "reference": "df874ff48ae3b1833ea17fba7c21b31a4d682614", "shasum": "" }, "require": { "ext-simplexml": "*", - "php": "^8.1", - "symfony/framework-bundle": "^5.0 || ^6.0 || ^7.0", - "vimeo/psalm": "^5.16 || dev-master" + "php": ">=8.1", + "symfony/expression-language": "^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^5.0 || ^6.0 || ^7.0 || ^8.0", + "vimeo/psalm": "^6 || dev-master" }, "require-dev": { "doctrine/annotations": "^1.8|^2", - "doctrine/orm": "^2.9", + "doctrine/orm": "^2.9 || ^3.6", "phpunit/phpunit": "~7.5 || ~9.5", - "symfony/cache-contracts": "^1.0 || ^2.0", + "symfony/cache-contracts": "^1.0 || ^2.0 || ^3.0", "symfony/console": "*", - "symfony/form": "^5.0 || ^6.0 || ^7.0", - "symfony/messenger": "^5.0 || ^6.0 || ^7.0", + "symfony/form": "^5.0 || ^6.0 || ^7.0 || ^8.0", + "symfony/messenger": "^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/security-core": "*", - "symfony/serializer": "^5.0 || ^6.0 || ^7.0", + "symfony/serializer": "^5.0 || ^6.0 || ^7.0 || ^8.0", "symfony/validator": "*", "twig/twig": "^2.10 || ^3.0", "weirdan/codeception-psalm-module": "dev-master" @@ -13065,9 +14017,9 @@ "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.6" + "source": "https://github.com/psalm/psalm-plugin-symfony/tree/v5.3.0" }, - "time": "2024-12-21T08:46:26+00:00" + "time": "2026-02-12T11:24:16+00:00" }, { "name": "rector/rector", @@ -13128,6 +14080,78 @@ ], "time": "2024-11-08T13:59:10+00:00" }, + { + "name": "revolt/event-loop", + "version": "v1.0.8", + "source": { + "type": "git", + "url": "https://github.com/revoltphp/event-loop.git", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/revoltphp/event-loop/zipball/b6fc06dce8e9b523c9946138fa5e62181934f91c", + "reference": "b6fc06dce8e9b523c9946138fa5e62181934f91c", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^9", + "psalm/phar": "^5.15" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Revolt\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "ceesjank@gmail.com" + }, + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "Rock-solid event loop for concurrent PHP applications.", + "keywords": [ + "async", + "asynchronous", + "concurrency", + "event", + "event-loop", + "non-blocking", + "scheduler" + ], + "support": { + "issues": "https://github.com/revoltphp/event-loop/issues", + "source": "https://github.com/revoltphp/event-loop/tree/v1.0.8" + }, + "time": "2025-08-27T21:33:23+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -14780,24 +15804,26 @@ }, { "name": "vimeo/psalm", - "version": "5.26.1", + "version": "6.15.1", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0" + "reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", - "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/28dc127af1b5aecd52314f6f645bafc10d0e11f9", + "reference": "28dc127af1b5aecd52314f6f645bafc10d0e11f9", "shasum": "" }, "require": { - "amphp/amp": "^2.4.2", - "amphp/byte-stream": "^1.5", + "amphp/amp": "^3", + "amphp/byte-stream": "^2", + "amphp/parallel": "^2.3", "composer-runtime-api": "^2", "composer/semver": "^1.4 || ^2.0 || ^3.0", "composer/xdebug-handler": "^2.0 || ^3.0", + "danog/advanced-json-rpc": "^3.1", "dnoegel/php-xdg-base-dir": "^0.1.1", "ext-ctype": "*", "ext-dom": "*", @@ -14806,27 +15832,26 @@ "ext-mbstring": "*", "ext-simplexml": "*", "ext-tokenizer": "*", - "felixfbecker/advanced-json-rpc": "^3.1", - "felixfbecker/language-server-protocol": "^1.5.2", + "felixfbecker/language-server-protocol": "^1.5.3", "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", - "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", - "nikic/php-parser": "^4.17", - "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", - "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "netresearch/jsonmapper": "^5.0", + "nikic/php-parser": "^5.0.0", + "php": "~8.1.31 || ~8.2.27 || ~8.3.16 || ~8.4.3 || ~8.5.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0", "spatie/array-to-xml": "^2.17.0 || ^3.0", - "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", - "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" - }, - "conflict": { - "nikic/php-parser": "4.17.0" + "symfony/console": "^6.0 || ^7.0 || ^8.0", + "symfony/filesystem": "~6.3.12 || ~6.4.3 || ^7.0.3 || ^8.0", + "symfony/polyfill-php84": "^1.31.0" }, "provide": { "psalm/psalm": "self.version" }, "require-dev": { - "amphp/phpunit-util": "^2.0", + "amphp/phpunit-util": "^3", "bamarni/composer-bin-plugin": "^1.4", "brianium/paratest": "^6.9", + "danog/class-finder": "^0.4.8", + "dg/bypass-finals": "^1.5", "ext-curl": "*", "mockery/mockery": "^1.5", "nunomaduro/mock-final-classes": "^1.1", @@ -14834,10 +15859,10 @@ "phpstan/phpdoc-parser": "^1.6", "phpunit/phpunit": "^9.6", "psalm/plugin-mockery": "^1.1", - "psalm/plugin-phpunit": "^0.18", + "psalm/plugin-phpunit": "^0.19", "slevomat/coding-standard": "^8.4", "squizlabs/php_codesniffer": "^3.6", - "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" + "symfony/process": "^6.0 || ^7.0 || ^8.0" }, "suggest": { "ext-curl": "In order to send data to shepherd", @@ -14848,6 +15873,7 @@ "psalm-language-server", "psalm-plugin", "psalm-refactor", + "psalm-review", "psalter" ], "type": "project", @@ -14857,7 +15883,9 @@ "dev-2.x": "2.x-dev", "dev-3.x": "3.x-dev", "dev-4.x": "4.x-dev", - "dev-master": "5.x-dev" + "dev-5.x": "5.x-dev", + "dev-6.x": "6.x-dev", + "dev-master": "7.x-dev" } }, "autoload": { @@ -14872,6 +15900,10 @@ "authors": [ { "name": "Matthew Brown" + }, + { + "name": "Daniil Gentili", + "email": "daniil@daniil.it" } ], "description": "A static analysis tool for finding errors in PHP applications", @@ -14886,7 +15918,7 @@ "issues": "https://github.com/vimeo/psalm/issues", "source": "https://github.com/vimeo/psalm" }, - "time": "2024-09-08T18:53:08+00:00" + "time": "2026-02-07T19:27:16+00:00" }, { "name": "vincentlanglet/twig-cs-fixer", @@ -14967,22 +15999,22 @@ }, { "name": "weirdan/doctrine-psalm-plugin", - "version": "v2.9.0", + "version": "v2.10.0", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-doctrine.git", - "reference": "3db8e55b2ea15373338d2a3eab71c5f5a31c8b08" + "reference": "8d604c817976e156cd6f1cfab983eadd35b04a2f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-doctrine/zipball/3db8e55b2ea15373338d2a3eab71c5f5a31c8b08", - "reference": "3db8e55b2ea15373338d2a3eab71c5f5a31c8b08", + "url": "https://api.github.com/repos/psalm/psalm-plugin-doctrine/zipball/8d604c817976e156cd6f1cfab983eadd35b04a2f", + "reference": "8d604c817976e156cd6f1cfab983eadd35b04a2f", "shasum": "" }, "require": { "composer/semver": "^1.4 || ^2.0 || ^3.0", - "php": "^7.2 || ^8", - "vimeo/psalm": "^4.28|^5.0" + "php": "^8", + "vimeo/psalm": "^6" }, "conflict": { "doctrine/collections": "<1.8", @@ -15039,9 +16071,9 @@ ], "support": { "issues": "https://github.com/psalm/psalm-plugin-doctrine/issues", - "source": "https://github.com/psalm/psalm-plugin-doctrine/tree/v2.9.0" + "source": "https://github.com/psalm/psalm-plugin-doctrine/tree/v2.10.0" }, - "time": "2023-07-15T05:44:30+00:00" + "time": "2025-01-26T11:36:27+00:00" } ], "aliases": [], From 6f16a836257785f2214e0e5a252d5d65f7d66fac Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 11:55:02 +0100 Subject: [PATCH 13/38] 6601: Updated taskfile to get same name style --- README.md | 4 ++-- Taskfile.yml | 48 ++++++++++++++++++++++++------------------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 379c63fab..adad62db4 100644 --- a/README.md +++ b/README.md @@ -126,10 +126,10 @@ docker compose exec phpfpm bin/console lexik:jwt:generate-keypair To get started with the development setup, run the following task command: ```shell -task site-install +task install:site # or if you want to load fixtures as well -task site-install-with-fixtures +task install:site-with-fixtures ``` If you want to load fixtures manually, use the command (`--yes` for auto-confirming): diff --git a/Taskfile.yml b/Taskfile.yml index d0bd361af..088ee25f8 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -20,65 +20,65 @@ tasks: cmds: - "{{ .DOCKER_COMPOSE }} {{ .CLI_ARGS }}" - site-install: + install:site: prompt: "This will reset your setup. Continue?" desc: "Install new OS2Display." cmds: - task compose -- down - task compose -- pull - - task npm-install - - task compose-up - - task composer-install + - task install:npm + - task compose:up + - task install:composer - task db:migrate --yes - task fixtures:copy-assets - - task site-open + - task open silent: true - site-install-with-fixtures: + install:site-with-fixtures: prompt: "This will reset your setup. Continue?" desc: "Install new OS2Display with fixtures installed." cmds: - task compose -- down - task compose -- pull - - task npm-install - - task compose-up - - task composer-install + - task install:npm + - task compose:up + - task install:composer - task db:migrate --yes - task fixtures:load --yes - task fixtures:copy-assets - - task site-open + - task open silent: true - site-open: + open: desc: "Opens admin, docs and client." cmds: - - task site-open:admin - - task site-open:client - - task site-open:docs - - task site-open:templates + - task open:admin + - task open:client + - task open:docs + - task open:templates silent: true - site-open:admin: + open:admin: desc: "Opens admin site." cmds: - open http://{{ .BASE_URL }} - site-open:client: + open:client: desc: "Opens client site." cmds: - open http://{{ .BASE_URL }}/client - site-open:docs: + open:docs: desc: "Opens API docs page" cmds: - open http://{{ .BASE_URL }}/docs - site-open:templates: + open:templates: desc: "Opens templates site." cmds: - open http://{{ .BASE_URL }}/template - npm-install: + install:npm: desc: "Installs node dependencies with npm." cmds: - docker compose run --rm --volume "$PWD:/md" node npm install @@ -89,13 +89,13 @@ tasks: - task compose -- exec phpfpm composer {{.CLI_ARGS}} silent: true - compose-up: + compose:up: desc: "Runs docker compose up." cmds: - task compose -- up --detach --remove-orphans silent: true - composer-install: + install:composer: desc: "Installs dependencies with composer." cmds: - task composer -- install {{.COMPOSER_INSTALL_ARGUMENTS}} {{.CLI_ARGS}} @@ -177,7 +177,7 @@ tasks: desc: Apply fixtures cmds: - task compose -- exec phpfpm bin/console hautelook:fixtures:load --no-interaction - - task compose-up + - task compose:up silent: true db:migrate: @@ -185,7 +185,7 @@ tasks: desc: Run database migrations cmds: - task compose -- exec phpfpm bin/console doctrine:migrations:migrate --no-interaction - - task compose-up + - task compose:up silent: true test:api: From 7c07f676a153cdc17dfb01bd67e05fe4e11c6a64 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 12:09:24 +0100 Subject: [PATCH 14/38] 6601: Updated baseline after psaml upgrade --- psalm-baseline.xml | 1533 +++++++++++++++++++++++++++++++++++++++++++- psalm.xml | 12 - 2 files changed, 1531 insertions(+), 14 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 66e0b071e..5304ec920 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,16 +1,165 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + repeat(u($title)->length())]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + repeat(u($password)->length())]]> + + + + + + @@ -20,34 +169,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getKernel()->getProjectDir() : getcwd()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -55,6 +454,9 @@ + + + @@ -64,34 +466,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -99,7 +539,15 @@ + + + + + + + + @@ -108,6 +556,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + @@ -163,34 +636,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + modifiedAt]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + playlistSlides]]> @@ -212,18 +779,32 @@ + + + + + + + + + + + + + + @@ -232,18 +813,32 @@ + + + + + + + + + + + + + + @@ -252,13 +847,38 @@ + + + + + + + + + + + + + getTenant()]]> + + + + + + + + + + + + userRoleTenants->first()->getTenant()]]> @@ -276,43 +896,723 @@ getUserType()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getId()]]> + getId()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getId()]]> + getId()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -332,6 +1632,9 @@ + + + @@ -346,6 +1649,9 @@ + + + @@ -356,30 +1662,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + getPlaylist()]]> @@ -388,63 +1762,175 @@ + + + + getId()]]> + + + + getId()]]> getModifiedAt()]]> + + + + + + + getId()]]> + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + + + + + + + + + + + + getId()]]> + + + + + + + + + + + + + + getId()]]> getModifiedAt()]]> iriConverter->getIriFromResource($layout)]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + + + getId()]]> getModifiedAt()]]> + + + + + + + + + + + + getId()]]> getModifiedAt()]]> + + + + + + @@ -453,6 +1939,12 @@ + + + + + + getModifiedAt()]]> @@ -461,9 +1953,17 @@ + + + + + + + + getId()]]> getId()]]> @@ -472,12 +1972,41 @@ getId()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/psalm.xml b/psalm.xml index 2d36c754f..68f8dc238 100644 --- a/psalm.xml +++ b/psalm.xml @@ -16,18 +16,6 @@ - - - - - - - - - - - - From acfb51d75707d2642e3fd390319eb3830c0c50ab Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:51:56 +0100 Subject: [PATCH 15/38] 6600: Applied coding standards --- .github/workflows/docker_build_images_from_tag.yml | 1 - config/packages/pentatrion_vite.yaml | 4 ++-- infrastructure/Readme.md | 14 ++++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index fc80e7ce7..ca6421308 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -101,4 +101,3 @@ jobs: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} subject-digest: ${{ steps.push.outputs.digest }} push-to-registry: true - diff --git a/config/packages/pentatrion_vite.yaml b/config/packages/pentatrion_vite.yaml index c8b11e194..3b3ecaacf 100644 --- a/config/packages/pentatrion_vite.yaml +++ b/config/packages/pentatrion_vite.yaml @@ -1,4 +1,4 @@ # @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 when@prod: - pentatrion_vite: - cache: true + pentatrion_vite: + cache: true diff --git a/infrastructure/Readme.md b/infrastructure/Readme.md index 739f3172a..e311e9f0e 100644 --- a/infrastructure/Readme.md +++ b/infrastructure/Readme.md @@ -3,25 +3,27 @@ This folder contains the infrastructure files for building the `os2display/*` images. Two images are built: + - `os2display/display-api-service`: The web (php-fpm) application image - `os2display/display-api-service-nginx`: The API (nginx) server image -## Github Actions +## GitHub Actions -Both images are built automatically on push to the `devolp` branch, and on tag creation. They are tagged with the -same version as the application. +Both images are built automatically on push to the `develop` branch, and on tag creation. +They are tagged with the same version as the application. ## Docker Hub -Images are published to https://hub.docker.com/orgs/os2display +Images are published to ## Building images locally A script is provided to build the images locally: `build-n-push.sh` ## Build process -Both images uses multistage builds, with the first two stages being identical. And the final stage is optimized for -the specific image. + +Both images use multistage builds, with the first two stages being identical. +And the final stage is optimized for the specific image. This is done because both images requires files from both the `npm` and `composer` build stages. And while having a shared build stage when building locally is possible, it's not feasible when building on Github Actions. From a5486eaee22e164cf04f1ec8b7d5c4a7deb6ec93 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Wed, 18 Feb 2026 11:59:34 +0100 Subject: [PATCH 16/38] 6600: Removed composer audit from GitHub Actions --- .github/workflows/composer.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml index b93b0d81c..b068c235a 100644 --- a/.github/workflows/composer.yaml +++ b/.github/workflows/composer.yaml @@ -56,13 +56,3 @@ jobs: docker network create frontend docker compose run --rm phpfpm composer install docker compose run --rm phpfpm composer normalize --dry-run - - composer-audit: - runs-on: ubuntu-latest - strategy: - fail-fast: false - steps: - - uses: actions/checkout@v4 - - run: | - docker network create frontend - docker compose run --rm phpfpm composer audit --locked From c321bce67b842ca5940f4900f5a3106b3c8dc7ea Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 12:22:28 +0100 Subject: [PATCH 17/38] 6601: Updated image build actions to be dependent on release --- .../docker_build_images_from_tag.yml | 30 +++++++++++-------- ...evelop.yml => docker_build_stg_images.yml} | 2 +- .github/workflows/github_build_release.yml | 5 +--- 3 files changed, 19 insertions(+), 18 deletions(-) rename .github/workflows/{docker_build_images_from_develop.yml => docker_build_stg_images.yml} (98%) diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index ca6421308..7a6bcb121 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -1,8 +1,9 @@ --- on: - push: - tags: - - "*" + workflow_run: + workflows: ["Create Github Release"] + types: + - completed # This Action builds to os2display/* using ./infrastructure/* # @see https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-github-packages @@ -16,6 +17,7 @@ env: jobs: docker: + if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: @@ -26,6 +28,8 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v5 + with: + ref: ${{ github.event.workflow_run.head_branch }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -47,15 +51,17 @@ jobs: uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN }} + tags: | + type=raw,value=${{ github.event.workflow_run.head_branch }} - name: Build and push Docker image - id: push + id: push-main uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: ./infrastructure/display-api-service/ file: ./infrastructure/display-api-service/Dockerfile build-args: | - APP_VERSION=${{ github.ref }} + APP_VERSION=${{ github.event.workflow_run.head_branch }} push: true tags: ${{ steps.meta-main.outputs.tags }} labels: ${{ steps.meta-main.outputs.labels }} @@ -66,7 +72,7 @@ jobs: uses: actions/attest-build-provenance@v3 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN}} - subject-digest: ${{ steps.push.outputs.digest }} + subject-digest: ${{ steps.push-main.outputs.digest }} push-to-registry: true # Build Nginx (depends on main) @@ -76,19 +82,17 @@ jobs: uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX }} - - - name: Get the tag - id: get_tag - run: echo ::set-output name=git_tag::$(echo $GITHUB_REF_NAME) + tags: | + type=raw,value=${{ github.event.workflow_run.head_branch }} - name: Build and push Docker image - id: push + id: push-nginx uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: context: ./infrastructure/nginx/ file: ./infrastructure/nginx/Dockerfile build-args: | - APP_VERSION=${{ steps.get_tag.outputs.git_tag }} + APP_VERSION=${{ github.event.workflow_run.head_branch }} push: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} @@ -99,5 +103,5 @@ jobs: uses: actions/attest-build-provenance@v3 with: subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} - subject-digest: ${{ steps.push.outputs.digest }} + subject-digest: ${{ steps.push-nginx.outputs.digest }} push-to-registry: true diff --git a/.github/workflows/docker_build_images_from_develop.yml b/.github/workflows/docker_build_stg_images.yml similarity index 98% rename from .github/workflows/docker_build_images_from_develop.yml rename to .github/workflows/docker_build_stg_images.yml index 0becba3b0..99426044e 100644 --- a/.github/workflows/docker_build_images_from_develop.yml +++ b/.github/workflows/docker_build_stg_images.yml @@ -2,7 +2,7 @@ on: push: branches: - - "develop" + - "release/*" # This Action builds to os2display/* using ./infrastructure/* name: Build docker image (develop) diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 559ac29a0..5bbd62799 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -3,7 +3,7 @@ on: push: tags: - - "*.*.*" + - "*" name: Create Github Release @@ -20,9 +20,6 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Install Task task runner - uses: go-task/setup-task@v1 - - name: Setup docker network run: | docker network create frontend From 0402005c04f5f2a9923653be414881b57bf75020 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 12:30:33 +0100 Subject: [PATCH 18/38] 6601: Update relase github action - permission error --- .github/workflows/github_build_release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 5bbd62799..5dbe2c467 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -36,6 +36,7 @@ jobs: - name: Cleanup after install run: | + sudo chown -R runner:runner . rm -rf docs rm -rf infrastructure rm -rf fixtures @@ -48,8 +49,7 @@ jobs: - name: Create archive run: | - tar \ - -zcf ../assets/${{ github.event.repository.name }}-${{ github.ref_name }}.tar.gz ./* + tar -zcf ../assets/${{ github.event.repository.name }}-${{ github.ref_name }}.tar.gz ./* - name: Create checksum run: sha256sum ../assets/${{ github.event.repository.name }}-${{ github.ref_name }}.tar.gz > ../assets/checksum.txt From 485869e5b88682419ed6c7da9a2c49d605a8e1ea Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 12:37:08 +0100 Subject: [PATCH 19/38] 6601: Fixed syntax error in image tag action --- .github/workflows/docker_build_images_from_tag.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index 7a6bcb121..d80960dee 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -22,7 +22,7 @@ jobs: # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: contents: read - packages: writes + packages: write attestations: write id-token: write steps: From f66f55e7b786b79da77c7ab79455077e178f156b Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 12:50:34 +0100 Subject: [PATCH 20/38] 6601: Added runner name to all actions - head_ref --- .github/workflows/apispec.yaml | 1 + .github/workflows/changelog.yaml | 1 + .github/workflows/composer.yaml | 1 + .github/workflows/composer_install.yaml | 1 + .github/workflows/docker_build_images_from_tag.yml | 1 + .github/workflows/docker_build_stg_images.yml | 1 + .github/workflows/doctrine.yaml | 1 + .github/workflows/github_build_release.yml | 1 + .github/workflows/javascript.yaml | 1 + .github/workflows/markdown.yaml | 1 + .github/workflows/php.yaml | 1 + .github/workflows/phpunit.yaml | 1 + .github/workflows/playwright.yaml | 1 + .github/workflows/psalm.yaml | 1 + .github/workflows/rector.yaml | 1 + .github/workflows/styles.yaml | 1 + .github/workflows/twig.yaml | 1 + .github/workflows/yaml.yaml | 1 + 18 files changed, 18 insertions(+) diff --git a/.github/workflows/apispec.yaml b/.github/workflows/apispec.yaml index 81de9fed9..4e31bf973 100644 --- a/.github/workflows/apispec.yaml +++ b/.github/workflows/apispec.yaml @@ -1,6 +1,7 @@ on: pull_request name: Api Spec +run-name: "Api Spec - ${{ github.head_ref || github.ref_name }}" jobs: apispec: diff --git a/.github/workflows/changelog.yaml b/.github/workflows/changelog.yaml index 483da6e95..563581199 100644 --- a/.github/workflows/changelog.yaml +++ b/.github/workflows/changelog.yaml @@ -7,6 +7,7 @@ ### Checks that changelog has been updated name: Changelog +run-name: "Changelog - ${{ github.head_ref || github.ref_name }}" on: pull_request: diff --git a/.github/workflows/composer.yaml b/.github/workflows/composer.yaml index b068c235a..6a4d41b6a 100644 --- a/.github/workflows/composer.yaml +++ b/.github/workflows/composer.yaml @@ -24,6 +24,7 @@ ### ``` name: Composer +run-name: "Composer - ${{ github.head_ref || github.ref_name }}" env: COMPOSE_USER: runner diff --git a/.github/workflows/composer_install.yaml b/.github/workflows/composer_install.yaml index 569a71b32..5ed5a630f 100644 --- a/.github/workflows/composer_install.yaml +++ b/.github/workflows/composer_install.yaml @@ -1,6 +1,7 @@ on: pull_request name: Composer install +run-name: "Composer install - ${{ github.head_ref || github.ref_name }}" jobs: test-composer-install: diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index d80960dee..85040e364 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -9,6 +9,7 @@ on: # @see https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-github-packages name: Build docker images (tag) +run-name: "Build release images - ${{ github.head_ref || github.ref_name }}" env: REGISTRY: ghcr.io diff --git a/.github/workflows/docker_build_stg_images.yml b/.github/workflows/docker_build_stg_images.yml index 99426044e..781b76f6d 100644 --- a/.github/workflows/docker_build_stg_images.yml +++ b/.github/workflows/docker_build_stg_images.yml @@ -6,6 +6,7 @@ on: # This Action builds to os2display/* using ./infrastructure/* name: Build docker image (develop) +run-name: "Build docker image (staging) - ${{ github.head_ref || github.ref_name }}" jobs: docker: diff --git a/.github/workflows/doctrine.yaml b/.github/workflows/doctrine.yaml index 411acc50f..5a27c071c 100644 --- a/.github/workflows/doctrine.yaml +++ b/.github/workflows/doctrine.yaml @@ -1,6 +1,7 @@ on: pull_request name: Doctrine +run-name: "Doctrine - ${{ github.head_ref || github.ref_name }}" jobs: validate-doctrine-shema: diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 5dbe2c467..af2825588 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -6,6 +6,7 @@ on: - "*" name: Create Github Release +run-name: "Create Github Release - ${{ github.head_ref || github.ref_name }}" permissions: contents: write diff --git a/.github/workflows/javascript.yaml b/.github/workflows/javascript.yaml index 801ddbe93..2c0317ce1 100644 --- a/.github/workflows/javascript.yaml +++ b/.github/workflows/javascript.yaml @@ -12,6 +12,7 @@ ### [Prettier](https://prettier.io/) exists. name: JavaScript +run-name: "JavaScript - ${{ github.head_ref || github.ref_name }}" on: pull_request: diff --git a/.github/workflows/markdown.yaml b/.github/workflows/markdown.yaml index 60fc0ee5c..a4b365d61 100644 --- a/.github/workflows/markdown.yaml +++ b/.github/workflows/markdown.yaml @@ -19,6 +19,7 @@ ### exists. name: Markdown +run-name: "Markdown - ${{ github.head_ref || github.ref_name }}" on: pull_request: diff --git a/.github/workflows/php.yaml b/.github/workflows/php.yaml index ee9679776..f62f7bd93 100644 --- a/.github/workflows/php.yaml +++ b/.github/workflows/php.yaml @@ -32,6 +32,7 @@ ### > project by adding a more important configuration file, `.php-cs-fixer.php`. name: Symfony PHP +run-name: "Symfony PHP - ${{ github.head_ref || github.ref_name }}" env: COMPOSE_USER: runner diff --git a/.github/workflows/phpunit.yaml b/.github/workflows/phpunit.yaml index 2a2e54889..26213011c 100644 --- a/.github/workflows/phpunit.yaml +++ b/.github/workflows/phpunit.yaml @@ -1,6 +1,7 @@ on: pull_request name: Test +run-name: "PHPUnit - ${{ github.head_ref || github.ref_name }}" jobs: phpunit: diff --git a/.github/workflows/playwright.yaml b/.github/workflows/playwright.yaml index 5b78012d6..63f7ccdeb 100644 --- a/.github/workflows/playwright.yaml +++ b/.github/workflows/playwright.yaml @@ -1,6 +1,7 @@ on: pull_request name: Test +run-name: "Playwright - ${{ github.head_ref || github.ref_name }}" env: COMPOSE_USER: runner diff --git a/.github/workflows/psalm.yaml b/.github/workflows/psalm.yaml index 6cbb222c9..56402c939 100644 --- a/.github/workflows/psalm.yaml +++ b/.github/workflows/psalm.yaml @@ -1,6 +1,7 @@ on: pull_request name: Psalm +run-name: "Psalm - ${{ github.head_ref || github.ref_name }}" jobs: psalm: diff --git a/.github/workflows/rector.yaml b/.github/workflows/rector.yaml index aa482e70b..42118596a 100644 --- a/.github/workflows/rector.yaml +++ b/.github/workflows/rector.yaml @@ -1,6 +1,7 @@ on: pull_request name: Rector +run-name: "Rector - ${{ github.head_ref || github.ref_name }}" jobs: rector: diff --git a/.github/workflows/styles.yaml b/.github/workflows/styles.yaml index edc796020..b95ddb08b 100644 --- a/.github/workflows/styles.yaml +++ b/.github/workflows/styles.yaml @@ -12,6 +12,7 @@ ### [Prettier](https://prettier.io/) exists. name: Styles +run-name: "Styles - ${{ github.head_ref || github.ref_name }}" on: pull_request: diff --git a/.github/workflows/twig.yaml b/.github/workflows/twig.yaml index 9dc424b45..62d9df81d 100644 --- a/.github/workflows/twig.yaml +++ b/.github/workflows/twig.yaml @@ -22,6 +22,7 @@ ### in the root of the project defines which files to check and rules to use. name: Twig +run-name: "Twig - ${{ github.head_ref || github.ref_name }}" env: COMPOSE_USER: runner diff --git a/.github/workflows/yaml.yaml b/.github/workflows/yaml.yaml index 1c0ada3f7..3776a90c0 100644 --- a/.github/workflows/yaml.yaml +++ b/.github/workflows/yaml.yaml @@ -19,6 +19,7 @@ ### Prettier format YAML files in the `config/` folder like Symfony expects. name: YAML +run-name: "YAML - ${{ github.head_ref || github.ref_name }}" on: pull_request: From c6577724d56f009c9c5c3383d31efb379adbd38e Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 13:02:04 +0100 Subject: [PATCH 21/38] 6601: Added image build on published release --- .../workflows/docker_build_images_from_tag.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml index 85040e364..ca190a0c5 100644 --- a/.github/workflows/docker_build_images_from_tag.yml +++ b/.github/workflows/docker_build_images_from_tag.yml @@ -1,9 +1,7 @@ --- on: - workflow_run: - workflows: ["Create Github Release"] - types: - - completed + release: + types: [published] # This Action builds to os2display/* using ./infrastructure/* # @see https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-github-packages @@ -18,7 +16,6 @@ env: jobs: docker: - if: ${{ github.event.workflow_run.conclusion == 'success' }} runs-on: ubuntu-latest # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. permissions: @@ -30,7 +27,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v5 with: - ref: ${{ github.event.workflow_run.head_branch }} + ref: ${{ github.event.release.tag_name }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -53,7 +50,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN }} tags: | - type=raw,value=${{ github.event.workflow_run.head_branch }} + type=raw,value=${{ github.event.release.tag_name }} - name: Build and push Docker image id: push-main @@ -62,7 +59,7 @@ jobs: context: ./infrastructure/display-api-service/ file: ./infrastructure/display-api-service/Dockerfile build-args: | - APP_VERSION=${{ github.event.workflow_run.head_branch }} + APP_VERSION=${{ github.event.release.tag_name }} push: true tags: ${{ steps.meta-main.outputs.tags }} labels: ${{ steps.meta-main.outputs.labels }} @@ -84,7 +81,7 @@ jobs: with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX }} tags: | - type=raw,value=${{ github.event.workflow_run.head_branch }} + type=raw,value=${{ github.event.release.tag_name }} - name: Build and push Docker image id: push-nginx @@ -93,7 +90,7 @@ jobs: context: ./infrastructure/nginx/ file: ./infrastructure/nginx/Dockerfile build-args: | - APP_VERSION=${{ github.event.workflow_run.head_branch }} + APP_VERSION=${{ github.event.release.tag_name }} push: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} From 919151b9435c6db75f81e83410639f6f3cb47208 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 14:24:41 +0100 Subject: [PATCH 22/38] 6601: Created combined workflow for release and image build --- .../docker_build_images_from_tag.yml | 105 ------------------ .github/workflows/github_build_release.yml | 101 ++++++++++++++++- 2 files changed, 97 insertions(+), 109 deletions(-) delete mode 100644 .github/workflows/docker_build_images_from_tag.yml diff --git a/.github/workflows/docker_build_images_from_tag.yml b/.github/workflows/docker_build_images_from_tag.yml deleted file mode 100644 index ca190a0c5..000000000 --- a/.github/workflows/docker_build_images_from_tag.yml +++ /dev/null @@ -1,105 +0,0 @@ ---- -on: - release: - types: [published] - -# This Action builds to os2display/* using ./infrastructure/* -# @see https://docs.github.com/en/actions/tutorials/publish-packages/publish-docker-images#publishing-images-to-github-packages - -name: Build docker images (tag) -run-name: "Build release images - ${{ github.head_ref || github.ref_name }}" - -env: - REGISTRY: ghcr.io - IMAGE_NAME_MAIN: ${{ github.repository }} - IMAGE_NAME_NGINX: ${{ github.repository }}-nginx - -jobs: - docker: - runs-on: ubuntu-latest - # Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job. - permissions: - contents: read - packages: write - attestations: write - id-token: write - steps: - - name: Checkout repository - uses: actions/checkout@v5 - with: - ref: ${{ github.event.release.tag_name }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - # Build main - - - name: Docker meta (main) - id: meta-main - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN }} - tags: | - type=raw,value=${{ github.event.release.tag_name }} - - - name: Build and push Docker image - id: push-main - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 - with: - context: ./infrastructure/display-api-service/ - file: ./infrastructure/display-api-service/Dockerfile - build-args: | - APP_VERSION=${{ github.event.release.tag_name }} - push: true - tags: ${{ steps.meta-main.outputs.tags }} - labels: ${{ steps.meta-main.outputs.labels }} - provenance: mode=max - sbom: true - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN}} - subject-digest: ${{ steps.push-main.outputs.digest }} - push-to-registry: true - - # Build Nginx (depends on main) - - - name: Docker meta (nginx) - id: meta-nginx - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX }} - tags: | - type=raw,value=${{ github.event.release.tag_name }} - - - name: Build and push Docker image - id: push-nginx - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 - with: - context: ./infrastructure/nginx/ - file: ./infrastructure/nginx/Dockerfile - build-args: | - APP_VERSION=${{ github.event.release.tag_name }} - push: true - tags: ${{ steps.meta-nginx.outputs.tags }} - labels: ${{ steps.meta-nginx.outputs.labels }} - provenance: mode=max - sbom: true - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} - subject-digest: ${{ steps.push-nginx.outputs.digest }} - push-to-registry: true diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index af2825588..ddf8de7b1 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -1,4 +1,5 @@ -# This workflow builds a GitHub release on tag creation. +# This workflow builds a GitHub release on tag creation and then builds and +# pushes Docker images to GitHub Container Registry. on: push: @@ -8,15 +9,14 @@ on: name: Create Github Release run-name: "Create Github Release - ${{ github.head_ref || github.ref_name }}" -permissions: - contents: write - env: COMPOSE_USER: runner jobs: create-release: runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Checkout uses: actions/checkout@v4 @@ -61,3 +61,96 @@ jobs: env: GITHUB_TOKEN: ${{ github.TOKEN }} shell: bash + + images: + needs: create-release + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + attestations: write + id-token: write + env: + REGISTRY: ghcr.io + IMAGE_NAME_MAIN: ${{ github.repository }} + IMAGE_NAME_NGINX: ${{ github.repository }}-nginx + steps: + - name: Checkout repository + uses: actions/checkout@v5 + with: + ref: ${{ github.ref_name }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Build main + + - name: Docker meta (main) + id: meta-main + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN }} + tags: | + type=raw,value=${{ github.ref_name }} + + - name: Build and push Docker image + id: push-main + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: ./infrastructure/display-api-service/ + file: ./infrastructure/display-api-service/Dockerfile + build-args: | + APP_VERSION=${{ github.ref_name }} + push: true + tags: ${{ steps.meta-main.outputs.tags }} + labels: ${{ steps.meta-main.outputs.labels }} + provenance: mode=max + sbom: true + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN}} + subject-digest: ${{ steps.push-main.outputs.digest }} + push-to-registry: true + + # Build Nginx (depends on main) + + - name: Docker meta (nginx) + id: meta-nginx + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX }} + tags: | + type=raw,value=${{ github.ref_name }} + + - name: Build and push Docker image + id: push-nginx + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: ./infrastructure/nginx/ + file: ./infrastructure/nginx/Dockerfile + build-args: | + APP_VERSION=${{ github.ref_name }} + push: true + tags: ${{ steps.meta-nginx.outputs.tags }} + labels: ${{ steps.meta-nginx.outputs.labels }} + provenance: mode=max + sbom: true + + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v3 + with: + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} + subject-digest: ${{ steps.push-nginx.outputs.digest }} + push-to-registry: true From c7e65bd8b4e51fc3d842646eb0d04b12d7ef05eb Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 15:47:09 +0100 Subject: [PATCH 23/38] 6601: Updated and simplifyed docker image build --- .github/workflows/github_build_release.yml | 2 - infrastructure/{Readme.md => README.md} | 0 infrastructure/build-n-push.sh | 20 ++--- infrastructure/display-api-service/Dockerfile | 55 ++++++-------- .../display-api-service/docker-entrypoint.sh | 23 ------ infrastructure/nginx/Dockerfile | 75 ++----------------- 6 files changed, 41 insertions(+), 134 deletions(-) rename infrastructure/{Readme.md => README.md} (100%) delete mode 100644 infrastructure/display-api-service/docker-entrypoint.sh diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index ddf8de7b1..641b0037d 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -94,7 +94,6 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} # Build main - - name: Docker meta (main) id: meta-main uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 @@ -125,7 +124,6 @@ jobs: push-to-registry: true # Build Nginx (depends on main) - - name: Docker meta (nginx) id: meta-nginx uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 diff --git a/infrastructure/Readme.md b/infrastructure/README.md similarity index 100% rename from infrastructure/Readme.md rename to infrastructure/README.md diff --git a/infrastructure/build-n-push.sh b/infrastructure/build-n-push.sh index 04f244043..950cc28fe 100755 --- a/infrastructure/build-n-push.sh +++ b/infrastructure/build-n-push.sh @@ -2,26 +2,26 @@ set -eux -APP_VERSION=develop +APP_VERSION=3.0.0-beta1 docker pull itkdev/php8.4-fpm:alpine docker pull nginxinc/nginx-unprivileged:alpine -docker build --build-context repository-root=.. \ +docker buildx build \ --platform linux/amd64,linux/arm64 \ - --pull \ --no-cache \ + --pull \ --build-arg APP_VERSION=${APP_VERSION} \ - --tag=turegjorup/display-api-service:${APP_VERSION} \ - --file="display-api-service/Dockerfile" display-api-service + --tag=ghcr.io/itk-dev/display-api-service:${APP_VERSION} \ + --file="display-api-service/Dockerfile" ../ - -docker build --build-context repository-root=.. \ +docker buildx build \ --platform linux/amd64,linux/arm64 \ --no-cache \ + --pull \ --build-arg VERSION=${APP_VERSION} \ - --tag=turegjorup/display-api-service-nginx:${APP_VERSION} \ + --tag=ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} \ --file="nginx/Dockerfile" nginx -docker push os2display/display-api-service:${APP_VERSION} -docker push os2display/display-api-service-nginx:${APP_VERSION} +#docker push ghcr.io/itk-dev/display-api-service:${APP_VERSION} +#docker push ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 748268a43..5960b557c 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,5 +1,5 @@ ######## Clients [Screen|Admin] build ######## -FROM node:24-alpine AS client_app_builder +FROM --platform=$BUILDPLATFORM node:24-alpine AS client_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" @@ -10,44 +10,37 @@ ENV APP_CLIENT_PATH=/app WORKDIR ${APP_CLIENT_PATH} # Copy only necessary files for npm install -COPY --from=repository-root package.json package-lock.json vite.config.js ./ +COPY package.json package-lock.json vite.config.js ./ # Install dependencies RUN npm ci --no-audit --no-fund # Copy source files needed for build -COPY --from=repository-root assets/ ./assets/ -COPY --from=repository-root public/client/ ./public/client/ +COPY assets/ ./assets/ +COPY public/client/ ./public/client/ # Build the application with version info RUN npm run build ######### API backend build ######## -FROM itkdev/php8.4-fpm:alpine AS api_app_builder +FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:latest AS api_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" ENV APP_CLIENT_PATH=/app \ APP_API_PATH=/var/www/html -USER root - -# Add composer in from the official composer image (also alpine). -COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer - WORKDIR ${APP_API_PATH} -USER deploy - # Copy only composer files first for better layer caching -COPY --chown=deploy:deploy --from=repository-root composer.json composer.lock symfony.lock ${APP_API_PATH}/ +COPY composer.json composer.lock symfony.lock ${APP_API_PATH}/ # Pre-install composer packages first (better image layer caching) - application code not present so have to be re-run RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts # Copy application source (needed for build step) -COPY --chown=deploy:deploy --from=repository-root ./ ${APP_API_PATH}/ +COPY ./ ${APP_API_PATH}/ # Copy javascript build files. This ensures that vite manifest files are availiable when "composer insatll" # triggers a "cache:clear" enabling the vite bundle to generate cache configuration files @@ -57,23 +50,34 @@ COPY --chown=deploy:deploy --from=client_app_builder ${APP_CLIENT_PATH}/public/b # Re-run composer install after application code copied to image to complete install RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative +# Remove files we do not need to the final image +RUN rm -rf \ + docker-compose.* \ + package* \ + phpstan.dist.neon \ + psalm* \ + playwright.* \ + phpunit.* \ + rector.php \ + Taskfile.yml \ + .markdown* \ + .php-cs-fixer.dist.php \ + .twig-cs-fixer.dist.php \ + .prettier \ + vite.config.js ######## PHP-FPM (API) production image ######## -FROM itkdev/php8.4-fpm:alpine +FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " ENV APP_CLIENT_PATH=/app \ APP_API_PATH=/var/www/html \ APP_ENV=prod \ COMPOSER_VERSION=2 \ - - # OpCache PHP_OPCACHE_ENABLED=1 \ PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \ PHP_OPCACHE_MAX_ACCELERATED_FILES=20000 \ PHP_OPCACHE_MEMORY_CONSUMPTION=256 \ - - # FPM pool PHP_PM_TYPE="dynamic" \ PHP_PM_MAX_CHILDREN="24" \ PHP_PM_MAX_REQUESTS="0" \ @@ -81,19 +85,6 @@ ENV APP_CLIENT_PATH=/app \ PHP_PM_MIN_SPARE_SERVERS="5" \ PHP_PM_MAX_SPARE_SERVERS="10" -USER root - -# Add composer needed to run optimizations after config is loaded. -COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer - -# Download Prometheus php-fpm export. -COPY --from=hipages/php-fpm_exporter:2.2.0 /php-fpm_exporter /usr/local/bin/php-fpm_exporter - -COPY docker-entrypoint.sh /usr/local/bin/ -RUN chmod +x /usr/local/bin/docker-entrypoint.sh - -USER deploy - WORKDIR ${APP_API_PATH} # Install the api application. diff --git a/infrastructure/display-api-service/docker-entrypoint.sh b/infrastructure/display-api-service/docker-entrypoint.sh deleted file mode 100644 index 744897e8b..000000000 --- a/infrastructure/display-api-service/docker-entrypoint.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh - -set -eux - -## Dump dotenv files into PHP for better performance. -## @see https://symfony.com/doc/6.4/configuration.html#configuring-environment-variables-in-production -composer dump-env prod - -## Warm-up Symfony cache (with the current configuration). -/var/www/html/bin/console --env=prod cache:warmup - -## Set selected composer version. Default version 2. -if [ ! -z "${COMPOSER_VERSION}" ]; then - if [ "${COMPOSER_VERSION}" = "1" ]; then - ln -fs /usr/bin/composer1 /home/deploy/bin/composer - else - ln -fs /usr/bin/composer2 /home/deploy/bin/composer - fi -else - ln -fs /usr/bin/composer2 /home/deploy/bin/composer -fi - -exec php-fpm "$@" diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 5bf5c00f7..bf47fe61e 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,72 +1,14 @@ -######## Clients [Screen|Admin] build ######## -FROM node:24-alpine AS client_app_builder -LABEL maintainer="ITK Dev " - ARG APP_VERSION="develop" -ARG APP_RELEASE_VERSION="develop" -ARG APP_RELEASE_TIMESTAMP=0 - -ENV APP_CLIENT_PATH=/app -WORKDIR ${APP_CLIENT_PATH} - -# Copy only necessary files for npm install -COPY --from=repository-root package.json package-lock.json vite.config.js ./ - -# Install dependencies -RUN npm ci --no-audit --no-fund - -# Copy source files needed for build -COPY --from=repository-root assets/ ./assets/ - -# Build the application with version info -RUN npm run build - - -######### API backend build ######## -FROM itkdev/php8.4-fpm:alpine AS api_app_builder -LABEL maintainer="ITK Dev " - -ARG APP_VERSION="develop" -ENV APP_CLIENT_PATH=/app \ - APP_API_PATH=/var/www/html - -USER root - -# Add composer in from the official composer image (also alpine). -COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer - -WORKDIR ${APP_API_PATH} - -USER deploy - -# Copy only composer files first for better layer caching -COPY --chown=deploy:deploy --from=repository-root composer.json composer.lock symfony.lock ${APP_API_PATH}/ - -# Pre-install composer packages first (better image layer caching) - application code not present so have to be re-run -RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts - -# Copy application source (needed for build step) -COPY --chown=deploy:deploy --from=repository-root ./ ${APP_API_PATH}/ - -# Copy javascript build files. This ensures that vite manifest files are availiable when "composer insatll" -# triggers a "cache:clear" enabling the vite bundle to generate cache configuration files -# @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 -COPY --chown=deploy:deploy --from=client_app_builder ${APP_CLIENT_PATH}/public/build ./public/build - -# Re-run composer install after application code copied to image to complete install -RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative - +FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/display-api-service:${APP_VERSION} AS app ######## Nginx production image ######## -FROM nginxinc/nginx-unprivileged:alpine +FROM --platform=$BUILDPLATFORM nginxinc/nginx-unprivileged:alpine LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" ARG APP_RELEASE_VERSION="develop" ARG APP_RELEASE_TIMESTAMP=0 -ARG UID=101 -ARG GID=101 ENV APP_CLIENT_PATH=/app \ APP_API_PATH=/var/www/html \ @@ -76,21 +18,20 @@ ENV APP_CLIENT_PATH=/app \ WORKDIR ${APP_API_PATH} +USER root + # Create directory and copy built client assets RUN mkdir -p ${APP_API_PATH}/public -COPY --from=api_app_builder --chown=$UID:0 ${APP_API_PATH}/public ./public - -# Copy configuration and entrypoint script -COPY --chown=$UID:0 etc /etc/nginx +COPY --from=app --chown=nginx:nginx ${APP_API_PATH}/public ./public -# Set proper permissions (files are already owned by $UID:0 from COPY --chown) -RUN chmod -R g+w ${APP_API_PATH} +# Copy configuration +COPY --chown=nginx:nginx etc /etc/nginx # Add health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:${NGINX_PORT}/health || exit 1 -USER $UID +USER nginx EXPOSE ${NGINX_PORT} From fcffcda5763f30485f1d75abae079a776fc97e0a Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 15:51:52 +0100 Subject: [PATCH 24/38] 6601: Changed build context in actions --- .github/workflows/github_build_release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index 641b0037d..b3928f8da 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -106,7 +106,7 @@ jobs: id: push-main uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: - context: ./infrastructure/display-api-service/ + context: . file: ./infrastructure/display-api-service/Dockerfile build-args: | APP_VERSION=${{ github.ref_name }} From 983ae8b8db9ac3785c0df5c4664e95b335656eee Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 16:42:01 +0100 Subject: [PATCH 25/38] 6601: More simple docker build process --- .dockerignore | 15 +++++- infrastructure/build-n-push.sh | 7 +-- infrastructure/display-api-service/Dockerfile | 51 +++---------------- infrastructure/nginx/Dockerfile | 15 ++---- infrastructure/nginx/etc/nginx.conf | 2 +- .../nginx/etc/templates/default.conf.template | 2 +- 6 files changed, 32 insertions(+), 60 deletions(-) diff --git a/.dockerignore b/.dockerignore index fc10ce7dc..ed42bd707 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,11 +2,10 @@ !/.git/config # Unneeded application files -/.docker/data/README.md +/.docker /.github /docs /fixtures -/infrastructure /public/build /public/fixtures /public/media/* @@ -55,3 +54,15 @@ launch.json ###> vincentlanglet/twig-cs-fixer ### /.twig-cs-fixer.cache ###< vincentlanglet/twig-cs-fixer ### + +docker-compose.* +phpstan.dist.neon +psalm* +playwright.* +phpunit.* +rector.php +Taskfile.yml +.markdown* +.php-cs-fixer.dist.php +.twig-cs-fixer.dist.php +.prettier diff --git a/infrastructure/build-n-push.sh b/infrastructure/build-n-push.sh index 950cc28fe..1190411e8 100755 --- a/infrastructure/build-n-push.sh +++ b/infrastructure/build-n-push.sh @@ -15,13 +15,14 @@ docker buildx build \ --tag=ghcr.io/itk-dev/display-api-service:${APP_VERSION} \ --file="display-api-service/Dockerfile" ../ +docker push ghcr.io/itk-dev/display-api-service:${APP_VERSION} + docker buildx build \ --platform linux/amd64,linux/arm64 \ --no-cache \ --pull \ - --build-arg VERSION=${APP_VERSION} \ + --build-arg APP_VERSION=${APP_VERSION} \ --tag=ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} \ --file="nginx/Dockerfile" nginx -#docker push ghcr.io/itk-dev/display-api-service:${APP_VERSION} -#docker push ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} +docker push ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 5960b557c..7d7eed290 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -3,11 +3,9 @@ FROM --platform=$BUILDPLATFORM node:24-alpine AS client_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" -ARG APP_RELEASE_VERSION="develop" -ARG APP_RELEASE_TIMESTAMP=0 -ENV APP_CLIENT_PATH=/app -WORKDIR ${APP_CLIENT_PATH} +RUN mkdir -p /app +WORKDIR /app # Copy only necessary files for npm install COPY package.json package-lock.json vite.config.js ./ @@ -17,7 +15,6 @@ RUN npm ci --no-audit --no-fund # Copy source files needed for build COPY assets/ ./assets/ -COPY public/client/ ./public/client/ # Build the application with version info RUN npm run build @@ -28,51 +25,23 @@ FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:latest AS api_app_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" -ENV APP_CLIENT_PATH=/app \ - APP_API_PATH=/var/www/html -WORKDIR ${APP_API_PATH} +WORKDIR /app # Copy only composer files first for better layer caching -COPY composer.json composer.lock symfony.lock ${APP_API_PATH}/ +COPY --chown=deploy:deploy . ./ -# Pre-install composer packages first (better image layer caching) - application code not present so have to be re-run -RUN APP_ENV=prod composer install --no-dev -o --classmap-authoritative --no-scripts - -# Copy application source (needed for build step) -COPY ./ ${APP_API_PATH}/ - -# Copy javascript build files. This ensures that vite manifest files are availiable when "composer insatll" -# triggers a "cache:clear" enabling the vite bundle to generate cache configuration files -# @see https://symfony-vite.pentatrion.com/guide/performance.html#caching-configuration-files-%F0%9F%8F%83 -COPY --chown=deploy:deploy --from=client_app_builder ${APP_CLIENT_PATH}/public/build ./public/build - -# Re-run composer install after application code copied to image to complete install +# Composer packages first RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative # Remove files we do not need to the final image -RUN rm -rf \ - docker-compose.* \ - package* \ - phpstan.dist.neon \ - psalm* \ - playwright.* \ - phpunit.* \ - rector.php \ - Taskfile.yml \ - .markdown* \ - .php-cs-fixer.dist.php \ - .twig-cs-fixer.dist.php \ - .prettier \ - vite.config.js +RUN rm -rf package* vite.config.js assets ######## PHP-FPM (API) production image ######## FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " -ENV APP_CLIENT_PATH=/app \ - APP_API_PATH=/var/www/html \ - APP_ENV=prod \ +ENV APP_ENV=prod \ COMPOSER_VERSION=2 \ PHP_OPCACHE_ENABLED=1 \ PHP_OPCACHE_VALIDATE_TIMESTAMPS=0 \ @@ -85,12 +54,8 @@ ENV APP_CLIENT_PATH=/app \ PHP_PM_MIN_SPARE_SERVERS="5" \ PHP_PM_MAX_SPARE_SERVERS="10" -WORKDIR ${APP_API_PATH} - # Install the api application. -COPY --chown=deploy:deploy --from=api_app_builder ${APP_API_PATH} . +COPY --chown=deploy:deploy --from=api_app_builder /app . RUN mkdir -p ./config/secrets -WORKDIR ${APP_API_PATH} - CMD [ "docker-entrypoint.sh" ] diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index bf47fe61e..66a401205 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,4 +1,5 @@ ARG APP_VERSION="develop" + FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/display-api-service:${APP_VERSION} AS app @@ -6,23 +7,17 @@ FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/display-api-service:${APP_VERSION FROM --platform=$BUILDPLATFORM nginxinc/nginx-unprivileged:alpine LABEL maintainer="ITK Dev " -ARG APP_VERSION="develop" -ARG APP_RELEASE_VERSION="develop" -ARG APP_RELEASE_TIMESTAMP=0 - -ENV APP_CLIENT_PATH=/app \ - APP_API_PATH=/var/www/html \ - NGINX_PORT=8080 \ +ENV NGINX_PORT=8080 \ NGINX_SET_REAL_IP_FROM=172.17.0.0/16 \ NGINX_MAX_BODY_SIZE=10m -WORKDIR ${APP_API_PATH} +WORKDIR /app USER root # Create directory and copy built client assets -RUN mkdir -p ${APP_API_PATH}/public -COPY --from=app --chown=nginx:nginx ${APP_API_PATH}/public ./public +RUN mkdir -p ./public +COPY --from=app --chown=nginx:nginx /app/public ./public # Copy configuration COPY --chown=nginx:nginx etc /etc/nginx diff --git a/infrastructure/nginx/etc/nginx.conf b/infrastructure/nginx/etc/nginx.conf index 2fc6396f0..90db47241 100644 --- a/infrastructure/nginx/etc/nginx.conf +++ b/infrastructure/nginx/etc/nginx.conf @@ -12,7 +12,7 @@ events { } http { - open_file_cache max=10000 inactive=5m; + open_file_cache max=10000 inactive=5m; open_file_cache_valid 5m; open_file_cache_min_uses 5; open_file_cache_errors off; diff --git a/infrastructure/nginx/etc/templates/default.conf.template b/infrastructure/nginx/etc/templates/default.conf.template index 52269bea8..45ccabf04 100644 --- a/infrastructure/nginx/etc/templates/default.conf.template +++ b/infrastructure/nginx/etc/templates/default.conf.template @@ -8,7 +8,7 @@ server { listen [::]:${NGINX_PORT}; server_name localhost; - root /var/www/html/public; + root /app/public; index index.php index.html; # Health check endpoint From 33c6c2bab7dde1fbeebfcf4d7b4052275abfb294 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 16:56:01 +0100 Subject: [PATCH 26/38] 6601: Pull image before trying to build nginx --- .github/workflows/github_build_release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index b3928f8da..ede4492e9 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -141,6 +141,7 @@ jobs: build-args: | APP_VERSION=${{ github.ref_name }} push: true + pull: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} provenance: mode=max From 81bdf028cee6e9b605bfddc666b23ecf3ea5a8bb Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Wed, 18 Feb 2026 17:29:50 +0100 Subject: [PATCH 27/38] 6601: Fixed build image names in actions --- .github/workflows/github_build_release.yml | 21 +++------------------ infrastructure/build-n-push.sh | 9 +++++---- infrastructure/nginx/Dockerfile | 3 ++- 3 files changed, 10 insertions(+), 23 deletions(-) diff --git a/.github/workflows/github_build_release.yml b/.github/workflows/github_build_release.yml index ede4492e9..ea6bbe7c5 100644 --- a/.github/workflows/github_build_release.yml +++ b/.github/workflows/github_build_release.yml @@ -102,7 +102,7 @@ jobs: tags: | type=raw,value=${{ github.ref_name }} - - name: Build and push Docker image + - name: Build and push Docker image (main) id: push-main uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: @@ -113,16 +113,8 @@ jobs: push: true tags: ${{ steps.meta-main.outputs.tags }} labels: ${{ steps.meta-main.outputs.labels }} - provenance: mode=max sbom: true - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MAIN}} - subject-digest: ${{ steps.push-main.outputs.digest }} - push-to-registry: true - # Build Nginx (depends on main) - name: Docker meta (nginx) id: meta-nginx @@ -132,7 +124,7 @@ jobs: tags: | type=raw,value=${{ github.ref_name }} - - name: Build and push Docker image + - name: Build and push Docker image (nginx) id: push-nginx uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 with: @@ -140,16 +132,9 @@ jobs: file: ./infrastructure/nginx/Dockerfile build-args: | APP_VERSION=${{ github.ref_name }} + APP_IMAGE=${{ env.IMAGE_NAME_MAIN }} push: true pull: true tags: ${{ steps.meta-nginx.outputs.tags }} labels: ${{ steps.meta-nginx.outputs.labels }} - provenance: mode=max sbom: true - - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v3 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_NGINX}} - subject-digest: ${{ steps.push-nginx.outputs.digest }} - push-to-registry: true diff --git a/infrastructure/build-n-push.sh b/infrastructure/build-n-push.sh index 1190411e8..feae48ab7 100755 --- a/infrastructure/build-n-push.sh +++ b/infrastructure/build-n-push.sh @@ -12,17 +12,18 @@ docker buildx build \ --no-cache \ --pull \ --build-arg APP_VERSION=${APP_VERSION} \ - --tag=ghcr.io/itk-dev/display-api-service:${APP_VERSION} \ + --tag=ghcr.io/itk-dev/os2display-api-service:${APP_VERSION} \ --file="display-api-service/Dockerfile" ../ -docker push ghcr.io/itk-dev/display-api-service:${APP_VERSION} +docker push ghcr.io/itk-dev/os2display-api-service:${APP_VERSION} docker buildx build \ --platform linux/amd64,linux/arm64 \ --no-cache \ --pull \ --build-arg APP_VERSION=${APP_VERSION} \ - --tag=ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} \ + --build-arg APP_IMAGE=os2display-api-service \ + --tag=ghcr.io/itk-dev/os2display-api-service-nginx:${APP_VERSION} \ --file="nginx/Dockerfile" nginx -docker push ghcr.io/itk-dev/display-api-service-nginx:${APP_VERSION} +docker push ghcr.io/itk-dev/os2display-api-service-nginx:${APP_VERSION} diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 66a401205..5e4e95525 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,6 +1,7 @@ ARG APP_VERSION="develop" +ARG APP_IMAGE="os2display-api-service" -FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/display-api-service:${APP_VERSION} AS app +FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/os2display-api-service:${APP_VERSION} AS app ######## Nginx production image ######## From 77e6709898e109afdc122c4e13cc52f683e362e0 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Fri, 20 Feb 2026 14:38:12 +0100 Subject: [PATCH 28/38] 6601: Do not remove assets in php image --- infrastructure/display-api-service/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 7d7eed290..f7dbb8181 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -35,7 +35,7 @@ COPY --chown=deploy:deploy . ./ RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative # Remove files we do not need to the final image -RUN rm -rf package* vite.config.js assets +RUN rm -rf package* vite.config.js ######## PHP-FPM (API) production image ######## FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:alpine From b01c3fd5e803848b9936ca92ad6273d66903aec1 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Fri, 20 Feb 2026 14:55:45 +0100 Subject: [PATCH 29/38] 6601: Ensured built assets in php image --- infrastructure/display-api-service/Dockerfile | 17 +++++++++++++---- infrastructure/nginx/Dockerfile | 7 ++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index f7dbb8181..2a4551569 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,5 +1,7 @@ -######## Clients [Screen|Admin] build ######## -FROM --platform=$BUILDPLATFORM node:24-alpine AS client_app_builder +################################ +# Assets build +################################ +FROM --platform=$BUILDPLATFORM node:24-alpine AS assets_builder LABEL maintainer="ITK Dev " ARG APP_VERSION="develop" @@ -20,7 +22,9 @@ COPY assets/ ./assets/ RUN npm run build -######### API backend build ######## +################################ +# API backend build +################################ FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:latest AS api_app_builder LABEL maintainer="ITK Dev " @@ -34,10 +38,15 @@ COPY --chown=deploy:deploy . ./ # Composer packages first RUN APP_ENV=prod composer install --no-dev --optimize-autoloader --classmap-authoritative +COPY --chown=deploy:deploy --from=assets_builder /app/public/build /app/public/build + # Remove files we do not need to the final image RUN rm -rf package* vite.config.js -######## PHP-FPM (API) production image ######## + +################################ +# PHP-FPM (API) production image +################################ FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " diff --git a/infrastructure/nginx/Dockerfile b/infrastructure/nginx/Dockerfile index 5e4e95525..8d6c7ecab 100644 --- a/infrastructure/nginx/Dockerfile +++ b/infrastructure/nginx/Dockerfile @@ -1,10 +1,11 @@ ARG APP_VERSION="develop" ARG APP_IMAGE="os2display-api-service" -FROM --platform=$BUILDPLATFORM ghcr.io/itk-dev/os2display-api-service:${APP_VERSION} AS app +FROM --platform=$BUILDPLATFORM ghcr.io/${APP_IMAGE}:${APP_VERSION} AS app - -######## Nginx production image ######## +################################ +# Nginx production image +################################ FROM --platform=$BUILDPLATFORM nginxinc/nginx-unprivileged:alpine LABEL maintainer="ITK Dev " From aa6e49811b1261e74571de6c7966fbb1511b0936 Mon Sep 17 00:00:00 2001 From: Jesper Kristensen Date: Mon, 23 Feb 2026 14:50:31 +0100 Subject: [PATCH 30/38] 6601: Updated nginx configuration --- infrastructure/display-api-service/Dockerfile | 6 ++++-- .../nginx/etc/templates/default.conf.template | 10 ++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/infrastructure/display-api-service/Dockerfile b/infrastructure/display-api-service/Dockerfile index 2a4551569..1f0d6db63 100644 --- a/infrastructure/display-api-service/Dockerfile +++ b/infrastructure/display-api-service/Dockerfile @@ -1,5 +1,5 @@ ################################ -# Assets build +# Assets build ################################ FROM --platform=$BUILDPLATFORM node:24-alpine AS assets_builder LABEL maintainer="ITK Dev " @@ -45,7 +45,7 @@ RUN rm -rf package* vite.config.js ################################ -# PHP-FPM (API) production image +# PHP-FPM (API) production image ################################ FROM --platform=$BUILDPLATFORM itkdev/php8.4-fpm:alpine LABEL maintainer="ITK Dev " @@ -65,6 +65,8 @@ ENV APP_ENV=prod \ # Install the api application. COPY --chown=deploy:deploy --from=api_app_builder /app . + +# Symfony settings (warmup required to make vite assets work corretly) RUN mkdir -p ./config/secrets CMD [ "docker-entrypoint.sh" ] diff --git a/infrastructure/nginx/etc/templates/default.conf.template b/infrastructure/nginx/etc/templates/default.conf.template index 45ccabf04..eacfa67e2 100644 --- a/infrastructure/nginx/etc/templates/default.conf.template +++ b/infrastructure/nginx/etc/templates/default.conf.template @@ -1,8 +1,3 @@ -upstream api_backend { - server ${NGINX_FPM_SERVICE}; - keepalive 16; -} - server { listen ${NGINX_PORT}; listen [::]:${NGINX_PORT}; @@ -63,7 +58,7 @@ server { # Screen client online check should just serve static files location /client/online-check { - index index.html index.htm; + index index.html; } location = /robots.txt { @@ -98,7 +93,7 @@ server { # PHP-FPM handling location ~ ^/index\.php(/|$) { - fastcgi_pass api_backend; + fastcgi_pass ${NGINX_FPM_SERVICE}:${NGINX_FPM_PORT}; fastcgi_split_path_info ^(.+\.php)(/.*)$; include fastcgi_params; @@ -126,7 +121,6 @@ server { return 404; } - # Send log message to files symlinked to stdout/stderr. sendfile on; keepalive_timeout 65; From 8f30b75fbde8337ec0e297d5645f1cfebcbafbfe Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:08:06 +0100 Subject: [PATCH 31/38] 6600: Fixed template title when loading new template --- src/Service/TemplateService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Service/TemplateService.php b/src/Service/TemplateService.php index 123a2b29c..6072ffe75 100644 --- a/src/Service/TemplateService.php +++ b/src/Service/TemplateService.php @@ -69,11 +69,11 @@ public function install(TemplateData $templateData, bool $update = false): void $ulid = Ulid::fromString($templateData->id); $template->setId($ulid); + $template->setTitle($templateData->title); $this->entityManager->persist($template); } - - if ($update) { + else if ($update) { $template->setTitle($templateData->title); } From 6587cb10bbc9ccd6139fc80f8331ed6e0c253e7a Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:11:11 +0100 Subject: [PATCH 32/38] 6600: Applied coding standards --- src/Service/TemplateService.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Service/TemplateService.php b/src/Service/TemplateService.php index 6072ffe75..c747a2a69 100644 --- a/src/Service/TemplateService.php +++ b/src/Service/TemplateService.php @@ -72,8 +72,7 @@ public function install(TemplateData $templateData, bool $update = false): void $template->setTitle($templateData->title); $this->entityManager->persist($template); - } - else if ($update) { + } elseif ($update) { $template->setTitle($templateData->title); } From addb8075d2c254a3ba6e2447df1823b84f97d375 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:13:45 +0100 Subject: [PATCH 33/38] 6600: Fixed screen layout title when loading new screen layout --- src/Service/ScreenLayoutService.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Service/ScreenLayoutService.php b/src/Service/ScreenLayoutService.php index 8414f4096..507e0dc5d 100644 --- a/src/Service/ScreenLayoutService.php +++ b/src/Service/ScreenLayoutService.php @@ -72,11 +72,10 @@ public function install(ScreenLayoutData $screenLayoutData, bool $update = false $ulid = Ulid::fromString($screenLayoutData->id); $screenLayout->setId($ulid); + $screenLayout->setTitle($screenLayoutData->title); $this->entityManager->persist($screenLayout); - } - - if ($update) { + } elseif ($update) { $screenLayout->setTitle($screenLayoutData->title); } From 3778212fbcaaa59102a010e3977bbb6fe010747c Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:08:37 +0200 Subject: [PATCH 34/38] 6871: Added infrastructure documentation --- README.md | 48 ++++++++++++++++++++++++++-------------- docs/infrastructure.png | Bin 0 -> 157786 bytes 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 docs/infrastructure.png diff --git a/README.md b/README.md index adad62db4..7f5c8da73 100644 --- a/README.md +++ b/README.md @@ -9,23 +9,24 @@ 5. [Taskfile](#taskfile) 6. [Development setup](#development-setup) 7. [Production setup](#production-setup) -8. [Coding standards](#coding-standards) -9. [Stateless](#stateless) -10. [OIDC providers](#oidc-providers) -11. [JWT Auth](#jwt-auth) -12. [Test](#test) -13. [API specification and generated code](#api-specification-and-generated-code) -14. [Configuration](#configuration) -15. [Rest API & Relationships](#rest-api--relationships) -16. [Error codes in the Client](#error-codes-in-the-client) -17. [Preview mode in the Client](#preview-mode-in-the-client) -18. [Feeds](#feeds) -19. [Custom Templates](#custom-templates) -20. [Static Analysis](#static-analysis) -21. [Upgrade Guide](#upgrade-guide) -22. [Tenants](#tenants) -23. [Screen layouts](#screen-layouts) -24. [Templates](#templates) +8. [Infrastructure](#infrastructure) +9. [Coding standards](#coding-standards) +10. [Stateless](#stateless) +11. [OIDC providers](#oidc-providers) +12. [JWT Auth](#jwt-auth) +13. [Test](#test) +14. [API specification and generated code](#api-specification-and-generated-code) +15. [Configuration](#configuration) +16. [Rest API & Relationships](#rest-api--relationships) +17. [Error codes in the Client](#error-codes-in-the-client) +18. [Preview mode in the Client](#preview-mode-in-the-client) +19. [Feeds](#feeds) +20. [Custom Templates](#custom-templates) +21. [Static Analysis](#static-analysis) +22. [Upgrade Guide](#upgrade-guide) +23. [Tenants](#tenants) +24. [Screen layouts](#screen-layouts) +25. [Templates](#templates) ## Description @@ -163,6 +164,19 @@ Use the `app:update` command to migrate and update templates to latest version: docker compose exec phpfpm bin/console app:update --no-interaction ``` +## Infrastructure + +When a new tag is created a GitHub release is created with built assets. + +After this, docker images are built and published in GitHub packages: + + +See for a docker based server setup, that uses these packages. + +TODO: Fix links after repository moves and renames. + +![Infrastructure overview](docs/infrastructure.png) + ## Coding standards Before a PR can be merged it has to pass the GitHub Actions checks. See `.github/workflows` for workflows that should diff --git a/docs/infrastructure.png b/docs/infrastructure.png new file mode 100644 index 0000000000000000000000000000000000000000..0cdbb9835937569b14744aa82910940a01b4e5cb GIT binary patch literal 157786 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%0DTsSV2`1160~mUg%eEZ`cqT>BepAh#I)N*E&v0 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 R48S*#bEoxBrJh9n@jqh8aH9YK literal 0 HcmV?d00001 From b76b123b2340889c859c68cc332639c7c8069114 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:28:46 +0200 Subject: [PATCH 35/38] 6871: Upgraded itk-dev/openid-connect-bundle to ^4.1 --- composer.json | 2 +- composer.lock | 81 +++++++++++++++++++++++++-------------------------- 2 files changed, 41 insertions(+), 42 deletions(-) diff --git a/composer.json b/composer.json index 30132d0cb..35d619ed5 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ "doctrine/doctrine-migrations-bundle": "^3.1", "doctrine/orm": "^2.9", "gesdinet/jwt-refresh-token-bundle": "^1.0", - "itk-dev/openid-connect-bundle": "^3.1", + "itk-dev/openid-connect-bundle": "^4.1", "justinrainbow/json-schema": "^5.2", "kubawerlos/php-cs-fixer-custom-fixers": "^3.11", "lexik/jwt-authentication-bundle": "^2.14", diff --git a/composer.lock b/composer.lock index ad195f4e6..ccb47f8c7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "567a746ddcb5a440c396fc6ea9cfa7ac", + "content-hash": "d4eec49aaac4f1294b58926d4944be05", "packages": [ { "name": "api-platform/core", @@ -2090,16 +2090,16 @@ }, { "name": "firebase/php-jwt", - "version": "v6.11.1", + "version": "v7.0.4", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66" + "reference": "e41f1bd7dbe3c5455c3f72d4338cfeb083b71931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", - "reference": "d1e91ecf8c598d073d0995afa8cd5c75c6e19e66", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/e41f1bd7dbe3c5455c3f72d4338cfeb083b71931", + "reference": "e41f1bd7dbe3c5455c3f72d4338cfeb083b71931", "shasum": "" }, "require": { @@ -2107,6 +2107,7 @@ }, "require-dev": { "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.5", "psr/cache": "^2.0||^3.0", @@ -2147,9 +2148,9 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.11.1" + "source": "https://github.com/firebase/php-jwt/tree/v7.0.4" }, - "time": "2025-04-09T20:32:01+00:00" + "time": "2026-03-27T21:17:19+00:00" }, { "name": "friendsofphp/php-cs-fixer", @@ -2807,35 +2808,35 @@ }, { "name": "itk-dev/openid-connect", - "version": "3.2.1", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/itk-dev/openid-connect.git", - "reference": "7bea58e5d8b338a1e0d260653ccf3f72fc2a4c2d" + "reference": "9e069c13a3b09105d67b3e364ae296dea2bbcbae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itk-dev/openid-connect/zipball/7bea58e5d8b338a1e0d260653ccf3f72fc2a4c2d", - "reference": "7bea58e5d8b338a1e0d260653ccf3f72fc2a4c2d", + "url": "https://api.github.com/repos/itk-dev/openid-connect/zipball/9e069c13a3b09105d67b3e364ae296dea2bbcbae", + "reference": "9e069c13a3b09105d67b3e364ae296dea2bbcbae", "shasum": "" }, "require": { "ext-json": "*", "ext-openssl": "*", - "firebase/php-jwt": "^6.8", + "firebase/php-jwt": "^7.0", "league/oauth2-client": "^2.6", - "php": "^8.1", + "php": "^8.3", "psr/cache": "^2.0 || ^3.0", "psr/http-client": "^1.0", "robrichards/xmlseclibs": "^3.1" }, "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", - "escapestudios/symfony2-coding-standard": "^3.12", - "mockery/mockery": "^1.4", - "phpunit/php-code-coverage": "^9.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.0" + "ergebnis/composer-normalize": "^2.50", + "friendsofphp/php-cs-fixer": "^3.75", + "mockery/mockery": "^1.6.12", + "phpstan/phpstan": "^2.1.40", + "phpunit/php-code-coverage": "^12", + "phpunit/phpunit": "^12" }, "type": "library", "autoload": { @@ -2864,45 +2865,43 @@ "description": "OpenID connect configuration package", "support": { "issues": "https://github.com/itk-dev/openid-connect/issues", - "source": "https://github.com/itk-dev/openid-connect/tree/3.2.1" + "source": "https://github.com/itk-dev/openid-connect/tree/4.1.0" }, - "time": "2023-09-18T10:24:50+00:00" + "time": "2026-03-20T10:53:12+00:00" }, { "name": "itk-dev/openid-connect-bundle", - "version": "3.1.0", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/itk-dev/openid-connect-bundle.git", - "reference": "8ab0b9ccbe900571f0dd1c9854cd462c991b31e3" + "reference": "9e605801b027f98817aa10fbe5f33cbaa47a8fd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/itk-dev/openid-connect-bundle/zipball/8ab0b9ccbe900571f0dd1c9854cd462c991b31e3", - "reference": "8ab0b9ccbe900571f0dd1c9854cd462c991b31e3", + "url": "https://api.github.com/repos/itk-dev/openid-connect-bundle/zipball/9e605801b027f98817aa10fbe5f33cbaa47a8fd7", + "reference": "9e605801b027f98817aa10fbe5f33cbaa47a8fd7", "shasum": "" }, "require": { - "doctrine/orm": "^2.8", + "doctrine/orm": "^2.8 || ^3.0", "ext-json": "*", "ext-openssl": "*", - "itk-dev/openid-connect": "^3.1", - "php": "^8.1", - "symfony/cache": "^5.4|^6.0", - "symfony/framework-bundle": "^5.4|^6.0", - "symfony/security-bundle": "^5.4|^6.0", - "symfony/uid": "^5.4|^6.0", - "symfony/yaml": "^5.4|^6.0" + "itk-dev/openid-connect": "^4.0", + "php": "^8.3", + "symfony/cache": "^6.4 || ^7.0 || ^8.0", + "symfony/framework-bundle": "^6.4.13 || ^7.0 || ^8.0", + "symfony/security-bundle": "^6.4.13 || ^7.0 || ^8.0", + "symfony/uid": "^6.4 || ^7.0 || ^8.0", + "symfony/yaml": "^6.4 || ^7.0 || ^8.0" }, "require-dev": { "ergebnis/composer-normalize": "^2.28", - "escapestudios/symfony2-coding-standard": "^3.12", "friendsofphp/php-cs-fixer": "^3.11", - "kubawerlos/php-cs-fixer-custom-fixers": "^3.11", - "phpunit/phpunit": "^9.5", - "psalm/plugin-symfony": "^5.0", - "rector/rector": "^0.14.2", - "vimeo/psalm": "^5.0" + "phpstan/phpstan": "^2.1", + "phpunit/phpunit": "^12.0", + "rector/rector": "^2.0", + "symfony/runtime": "^6.4.13 || ^7.0 || ^8.0" }, "type": "symfony-bundle", "autoload": { @@ -2927,9 +2926,9 @@ "description": "Symfony bundle for openid-connect", "support": { "issues": "https://github.com/itk-dev/openid-connect-bundle/issues", - "source": "https://github.com/itk-dev/openid-connect-bundle/tree/3.1.0" + "source": "https://github.com/itk-dev/openid-connect-bundle/tree/4.1.0" }, - "time": "2023-08-03T12:08:33+00:00" + "time": "2026-03-20T10:52:03+00:00" }, { "name": "jms/metadata", From b04ab60fbc11dfc3ee052bb28c4c75a323706537 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:32:28 +0200 Subject: [PATCH 36/38] 6871: Changed composer php version to >= 8.4 --- composer.json | 2 +- composer.lock | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 35d619ed5..0cdba3b81 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "license": "proprietary", "type": "project", "require": { - "php": ">=8.3", + "php": ">=8.4", "ext-ctype": "*", "ext-fileinfo": "*", "ext-gd": "*", diff --git a/composer.lock b/composer.lock index ccb47f8c7..8000f6cda 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d4eec49aaac4f1294b58926d4944be05", + "content-hash": "576ea5d4c8981e57c636bbae1b3113f0", "packages": [ { "name": "api-platform/core", @@ -16090,7 +16090,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": ">=8.3", + "php": ">=8.4", "ext-ctype": "*", "ext-fileinfo": "*", "ext-gd": "*", From 51ac0d08234fdef9417a930386e5d8915299b6e6 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:35:28 +0200 Subject: [PATCH 37/38] 6871: Changed GitHub actions workflows to use php 8.4 --- .github/workflows/apispec.yaml | 2 +- .github/workflows/composer_install.yaml | 2 +- .github/workflows/doctrine.yaml | 2 +- .github/workflows/phpunit.yaml | 2 +- .github/workflows/psalm.yaml | 2 +- .github/workflows/rector.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/apispec.yaml b/.github/workflows/apispec.yaml index 4e31bf973..962ae966f 100644 --- a/.github/workflows/apispec.yaml +++ b/.github/workflows/apispec.yaml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/composer_install.yaml b/.github/workflows/composer_install.yaml index 5ed5a630f..0c7c56f51 100644 --- a/.github/workflows/composer_install.yaml +++ b/.github/workflows/composer_install.yaml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] name: Composer install in prod mode (PHP ${{ matrix.php}}) steps: - name: Checkout diff --git a/.github/workflows/doctrine.yaml b/.github/workflows/doctrine.yaml index 5a27c071c..940ff0227 100644 --- a/.github/workflows/doctrine.yaml +++ b/.github/workflows/doctrine.yaml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] name: Validate Schema (PHP ${{ matrix.php}}) services: mariadb: diff --git a/.github/workflows/phpunit.yaml b/.github/workflows/phpunit.yaml index 26213011c..d3f8334b1 100644 --- a/.github/workflows/phpunit.yaml +++ b/.github/workflows/phpunit.yaml @@ -25,7 +25,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] name: PHP Unit tests (PHP ${{ matrix.php }}) steps: - name: Checkout diff --git a/.github/workflows/psalm.yaml b/.github/workflows/psalm.yaml index 56402c939..ffbd118bc 100644 --- a/.github/workflows/psalm.yaml +++ b/.github/workflows/psalm.yaml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] name: Psalm (PHP ${{ matrix.php }}) steps: - name: Checkout diff --git a/.github/workflows/rector.yaml b/.github/workflows/rector.yaml index 42118596a..9baf3a5a0 100644 --- a/.github/workflows/rector.yaml +++ b/.github/workflows/rector.yaml @@ -9,7 +9,7 @@ jobs: strategy: fail-fast: false matrix: - php: ["8.3"] + php: ["8.4"] name: Rector (PHP ${{ matrix.php }}) steps: - name: Checkout From 513d9a799e6def0c3590eaf9071a11eed9658d01 Mon Sep 17 00:00:00 2001 From: Troels Ugilt Jensen <6103205+tuj@users.noreply.github.com> Date: Mon, 30 Mar 2026 10:51:14 +0200 Subject: [PATCH 38/38] 6871: Fixed psalm raised issues --- src/Command/Checksum/RecalculateChecksumCommand.php | 2 +- src/Security/AzureOidcAuthenticator.php | 3 ++- src/Service/RelationsChecksumCalculator.php | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Command/Checksum/RecalculateChecksumCommand.php b/src/Command/Checksum/RecalculateChecksumCommand.php index 43d5b53a9..a77d52d5c 100644 --- a/src/Command/Checksum/RecalculateChecksumCommand.php +++ b/src/Command/Checksum/RecalculateChecksumCommand.php @@ -24,7 +24,7 @@ name: 'app:checksum:recalculate', description: 'Recalculate relation checksums for slides and media entities' )] -class RecalculateChecksumCommand extends Command +final class RecalculateChecksumCommand extends Command { private const string OPTION_TENANT = 'tenant'; private const string OPTION_MODIFIED_AFTER = 'modified-after'; diff --git a/src/Security/AzureOidcAuthenticator.php b/src/Security/AzureOidcAuthenticator.php index f93be068a..427e297e7 100644 --- a/src/Security/AzureOidcAuthenticator.php +++ b/src/Security/AzureOidcAuthenticator.php @@ -96,6 +96,7 @@ public function authenticate(Request $request): Passport } // Check if user exists already - if not create a user + /* @var User|null $user */ $user = $this->entityManager->getRepository(User::class)->findOneBy(['providerId' => $providerId]); if (null === $user) { @@ -114,7 +115,7 @@ public function authenticate(Request $request): Passport if (self::OIDC_PROVIDER_INTERNAL === $provider) { // Set tenants from claims. - $oidcGroups = $claims[$this->oidcInternalClaimGroups] ?? []; + $oidcGroups = (array) ($claims[$this->oidcInternalClaimGroups] ?? []); $this->setTenantRoles($user, $oidcGroups); } diff --git a/src/Service/RelationsChecksumCalculator.php b/src/Service/RelationsChecksumCalculator.php index 2e76cf999..187fe4f72 100644 --- a/src/Service/RelationsChecksumCalculator.php +++ b/src/Service/RelationsChecksumCalculator.php @@ -16,7 +16,7 @@ * Extracted from RelationsChecksumListener to allow reuse in console commands * and other contexts outside Doctrine lifecycle events. */ -class RelationsChecksumCalculator +final 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',