diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2d19756c06..be4d021e85 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -33,7 +33,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: 8.3 + php-version: 8.5 tools: composer:v2 coverage: none diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6e73bbac0f..5ecdb95f77 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: - php-versions: ['8.3', '8.4'] + php-versions: ['8.3', '8.4', '8.5'] services: # Postgres is started for the Feature suite. The Unit suite does not need @@ -55,7 +55,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} - extensions: mbstring, xml, ctype, iconv, intl, pdo, pdo_mysql, pdo_pgsql, pgsql, tokenizer + extensions: mbstring, xml, ctype, iconv, intl, pdo, pdo_mysql, pdo_pgsql, pgsql, tokenizer, gd ini-values: post_max_size=256M, upload_max_filesize=256M coverage: none diff --git a/Dockerfile.all-in-one b/Dockerfile.all-in-one index 45b18a531b..b140532ad8 100644 --- a/Dockerfile.all-in-one +++ b/Dockerfile.all-in-one @@ -15,14 +15,14 @@ COPY ./VERSION /app/VERSION RUN yarn install --network-timeout 600000 --frozen-lockfile && yarn build # Use stable multi-arch serversideup/php image -FROM serversideup/php:8.3-fpm-alpine +FROM serversideup/php:8.5-fpm-alpine ENV PHP_OPCACHE_ENABLE=1 # Switch to root for installing extensions and packages USER root -RUN install-php-extensions intl +RUN install-php-extensions intl gd RUN apk add --no-cache nodejs yarn nginx supervisor dos2unix diff --git a/backend/Dockerfile b/backend/Dockerfile index 609a307da2..9d67d2f42c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,4 @@ -FROM serversideup/php:8.4-fpm-nginx-alpine +FROM serversideup/php:8.5-fpm-nginx-alpine ENV PHP_OPCACHE_ENABLE=1 @@ -9,7 +9,7 @@ RUN echo "" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf && \ echo "user = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf && \ echo "group = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf -RUN install-php-extensions intl imagick +RUN install-php-extensions intl imagick gd COPY --chown=www-data:www-data . . diff --git a/backend/Dockerfile.dev b/backend/Dockerfile.dev index e4f9153f54..668cc0e892 100644 --- a/backend/Dockerfile.dev +++ b/backend/Dockerfile.dev @@ -1,4 +1,4 @@ -FROM serversideup/php:8.4-fpm-nginx-alpine +FROM serversideup/php:8.5-fpm-nginx-alpine ENV PHP_OPCACHE_ENABLE=1 ENV NGINX_WEBROOT=/var/www/html/public @@ -12,7 +12,7 @@ COPY --chown=www-data:www-data . /var/www/html # Switch to root user to install PHP extensions USER root -RUN install-php-extensions intl imagick +RUN install-php-extensions intl imagick gd USER www-data RUN chmod -R 755 /var/www/html/storage \ diff --git a/backend/app/Exports/AffiliatesExport.php b/backend/app/Exports/AffiliatesExport.php index e3fbe83216..84b1cb3de4 100644 --- a/backend/app/Exports/AffiliatesExport.php +++ b/backend/app/Exports/AffiliatesExport.php @@ -4,9 +4,8 @@ use Carbon\Carbon; use HiEvents\DomainObjects\AffiliateDomainObject; -use HiEvents\Resources\Affiliate\AffiliateResource; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Concerns\WithMapping; @@ -23,9 +22,9 @@ public function withData(LengthAwarePaginator $affiliates): AffiliatesExport return $this; } - public function collection(): AnonymousResourceCollection + public function collection(): Collection { - return AffiliateResource::collection($this->affiliates); + return collect($this->affiliates->items()); } public function headings(): array diff --git a/backend/app/Exports/AttendeesExport.php b/backend/app/Exports/AttendeesExport.php index 2feffcc104..0a01087a5c 100644 --- a/backend/app/Exports/AttendeesExport.php +++ b/backend/app/Exports/AttendeesExport.php @@ -10,10 +10,8 @@ use HiEvents\DomainObjects\ProductDomainObject; use HiEvents\DomainObjects\ProductPriceDomainObject; use HiEvents\DomainObjects\QuestionDomainObject; -use HiEvents\Resources\Attendee\AttendeeResource; use HiEvents\Services\Domain\Question\QuestionAnswerFormatter; use Illuminate\Contracts\Pagination\LengthAwarePaginator; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Support\Collection; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; @@ -39,9 +37,11 @@ public function withData(LengthAwarePaginator|Collection $data, Collection $prod return $this; } - public function collection(): AnonymousResourceCollection + public function collection(): Collection { - return AttendeeResource::collection($this->data); + return $this->data instanceof Collection + ? $this->data + : collect($this->data->items()); } public function headings(): array diff --git a/backend/app/Exports/OrdersExport.php b/backend/app/Exports/OrdersExport.php index 3c38b4da08..66160fecc3 100644 --- a/backend/app/Exports/OrdersExport.php +++ b/backend/app/Exports/OrdersExport.php @@ -8,9 +8,7 @@ use HiEvents\DomainObjects\OrderDomainObject; use HiEvents\DomainObjects\OrderItemDomainObject; use HiEvents\DomainObjects\QuestionDomainObject; -use HiEvents\Resources\Order\OrderResource; use HiEvents\Services\Domain\Question\QuestionAnswerFormatter; -use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Maatwebsite\Excel\Concerns\FromCollection; @@ -35,9 +33,9 @@ public function withData(LengthAwarePaginator $orders, Collection $questions): O return $this; } - public function collection(): AnonymousResourceCollection + public function collection(): Collection { - return OrderResource::collection($this->orders); + return collect($this->orders->items()); } public function headings(): array diff --git a/backend/app/Exports/PromoCodesExport.php b/backend/app/Exports/PromoCodesExport.php index f75e7bee24..512592b684 100644 --- a/backend/app/Exports/PromoCodesExport.php +++ b/backend/app/Exports/PromoCodesExport.php @@ -2,7 +2,7 @@ namespace HiEvents\Exports; -use HiEvents\Resources\PromoCode\PromoCodeResource; +use Illuminate\Support\Collection; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; use Maatwebsite\Excel\Concerns\WithMapping; @@ -19,9 +19,11 @@ public function withData($data): PromoCodesExport return $this; } - public function collection() + public function collection(): Collection { - return PromoCodeResource::collection($this->data); + return $this->data instanceof Collection + ? $this->data + : collect(is_array($this->data) ? $this->data : $this->data->items()); } public function headings(): array diff --git a/backend/composer.json b/backend/composer.json index 7de5f3d59d..6a45976976 100644 --- a/backend/composer.json +++ b/backend/composer.json @@ -21,7 +21,7 @@ "laravel/vapor-core": "^2.37", "league/flysystem-aws-s3-v3": "^3.0", "liquid/liquid": "^1.4", - "maatwebsite/excel": "^3.1", + "maatwebsite/excel": "4.x-dev", "nette/php-generator": "^4.0", "php-open-source-saver/jwt-auth": "^2.1", "sentry/sentry-laravel": "^4.13", @@ -90,7 +90,7 @@ "php-http/discovery": true } }, - "minimum-stability": "stable", + "minimum-stability": "dev", "prefer-stable": true, "repositories": [ { diff --git a/backend/composer.lock b/backend/composer.lock index 928bccd11f..fc3882e364 100644 --- a/backend/composer.lock +++ b/backend/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": "4937f3c8d531e14340f7343aab700e17", + "content-hash": "d629c0ab94ca3eb682267d76a76cd4a0", "packages": [ { "name": "aws/aws-crt-php", @@ -3455,30 +3455,40 @@ }, { "name": "maatwebsite/excel", - "version": "3.1.69", + "version": "4.x-dev", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760" + "reference": "86cce13606e7cdf0f0b02007307c82d5c0b5fb3e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760", - "reference": "ae5d65b7c9a2fac43bff4d44f796ac95d7a8e760", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/86cce13606e7cdf0f0b02007307c82d5c0b5fb3e", + "reference": "86cce13606e7cdf0f0b02007307c82d5c0b5fb3e", "shasum": "" }, "require": { "composer/semver": "^3.3", "ext-json": "*", - "illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0||^12.0||^13.0", - "php": "^7.0||^8.0", - "phpoffice/phpspreadsheet": "^1.30.4", + "illuminate/support": "^12.0||^13.0", + "php": "^8.3", + "phpoffice/phpspreadsheet": "^5.3", "psr/simple-cache": "^1.0||^2.0||^3.0" }, "require-dev": { - "laravel/scout": "^7.0||^8.0||^9.0||^10.0||^11.0", - "orchestra/testbench": "^6.0||^7.0||^8.0||^9.0||^10.0||^11.0", - "predis/predis": "^1.1" + "brianium/paratest": "^7.19||^8.0", + "driftingly/rector-laravel": "^2.3", + "ext-sqlite3": "*", + "larastan/larastan": "^3.9", + "laravel/pint": "^1.0", + "laravel/scout": "^10.0||^11.0", + "orchestra/testbench": "^10.0||^11.0", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1.55", + "phpstan/phpstan-mockery": "^2.0", + "phpunit/phpunit": "^12.5.3||^13.0.0", + "predis/predis": "^1.1", + "rector/rector": "^2.4.2" }, "type": "library", "extra": { @@ -3520,7 +3530,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.69" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/4.x" }, "funding": [ { @@ -3532,7 +3542,7 @@ "type": "github" } ], - "time": "2026-04-30T20:03:58+00:00" + "time": "2026-05-24T11:02:38+00:00" }, { "name": "maennchen/zipstream-php", @@ -4853,16 +4863,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.30.4", + "version": "5.7.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9" + "reference": "9f55d3b9b7bcb1084fda8340e4b7ce4ed10cd0c8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9", - "reference": "02970383cc12e7bf0bc0707ea6e2e8ed23a7aec9", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/9f55d3b9b7bcb1084fda8340e4b7ce4ed10cd0c8", + "reference": "9f55d3b9b7bcb1084fda8340e4b7ce4ed10cd0c8", "shasum": "" }, "require": { @@ -4870,6 +4880,7 @@ "ext-ctype": "*", "ext-dom": "*", "ext-fileinfo": "*", + "ext-filter": "*", "ext-gd": "*", "ext-iconv": "*", "ext-libxml": "*", @@ -4880,30 +4891,30 @@ "ext-xmlwriter": "*", "ext-zip": "*", "ext-zlib": "*", - "ezyang/htmlpurifier": "^4.15", "maennchen/zipstream-php": "^2.1 || ^3.0", "markbaker/complex": "^3.0", "markbaker/matrix": "^3.0", - "php": ">=7.4.0 <8.5.0", + "php": "^8.1", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-main", - "doctrine/instantiator": "^1.5", - "dompdf/dompdf": "^1.0 || ^2.0 || ^3.0", + "dompdf/dompdf": "^2.0 || ^3.0", + "ext-intl": "*", "friendsofphp/php-cs-fixer": "^3.2", - "mitoteam/jpgraph": "^10.3", + "mitoteam/jpgraph": "^10.5", "mpdf/mpdf": "^8.1.1", "phpcompatibility/php-compatibility": "^9.3", - "phpstan/phpstan": "^1.1", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^8.5 || ^9.0", + "phpstan/phpstan": "^1.1 || ^2.0", + "phpstan/phpstan-deprecation-rules": "^1.0 || ^2.0", + "phpstan/phpstan-phpunit": "^1.0 || ^2.0", + "phpunit/phpunit": "^10.5", "squizlabs/php_codesniffer": "^3.7", "tecnickcom/tcpdf": "^6.5" }, "suggest": { "dompdf/dompdf": "Option for rendering PDF with PDF Writer", - "ext-intl": "PHP Internationalization Functions", + "ext-intl": "PHP Internationalization Functions, required for NumberFormat Wizard and StringHelper::setLocale()", "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", "mpdf/mpdf": "Option for rendering PDF with PDF Writer", "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer" @@ -4955,9 +4966,9 @@ ], "support": { "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", - "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.30.4" + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/5.7.0" }, - "time": "2026-04-19T06:00:39+00:00" + "time": "2026-04-20T02:42:17+00:00" }, { "name": "phpoption/phpoption", @@ -12934,9 +12945,10 @@ } ], "aliases": [], - "minimum-stability": "stable", + "minimum-stability": "dev", "stability-flags": { - "druc/laravel-langscanner": 20 + "druc/laravel-langscanner": 20, + "maatwebsite/excel": 20 }, "prefer-stable": true, "prefer-lowest": false, diff --git a/backend/config/database.php b/backend/config/database.php index a3d58d1988..c281b946f1 100644 --- a/backend/config/database.php +++ b/backend/config/database.php @@ -61,7 +61,7 @@ 'strict' => true, 'engine' => null, 'options' => extension_loaded('pdo_mysql') ? array_filter([ - PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + (PHP_VERSION_ID >= 80500 ? \Pdo\Mysql::ATTR_SSL_CA : PDO::MYSQL_ATTR_SSL_CA) => env('MYSQL_ATTR_SSL_CA'), ]) : [], ], diff --git a/backend/tests/Feature/Auth/ResetPasswordTest.php b/backend/tests/Feature/Auth/ResetPasswordTest.php index 643aba4c7e..d957619fd4 100644 --- a/backend/tests/Feature/Auth/ResetPasswordTest.php +++ b/backend/tests/Feature/Auth/ResetPasswordTest.php @@ -77,7 +77,6 @@ public function test_reset_password_with_valid_token(): void // extract the token from the email $reflection = new ReflectionClass($email); $tokenProperty = $reflection->getProperty('token'); - $tokenProperty->setAccessible(true); $token = $tokenProperty->getValue($email); $response2 = $this->getJson(self::RESET_PASSWORD_ROUTE . '/' . urlencode($token)); @@ -138,7 +137,6 @@ public function test_reset_password_with_old_password(): void // extract the token from the email $reflection = new ReflectionClass($email); $tokenProperty = $reflection->getProperty('token'); - $tokenProperty->setAccessible(true); $token = $tokenProperty->getValue($email); $response2 = $this->postJson(self::RESET_PASSWORD_ROUTE . '/' . urlencode($token), [