mirror of
https://github.com/MarijnDoeve/TijdVoorDeTest.git
synced 2026-07-05 23:20:18 +02:00
Compare commits
4 Commits
v0.1.3
..
d94eeced8c
| Author | SHA1 | Date | |
|---|---|---|---|
|
d94eeced8c
|
|||
|
7e09fcdafb
|
|||
|
d8b671046b
|
|||
|
cd63ef339f
|
@@ -28,7 +28,3 @@ updates:
|
|||||||
directory: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
- package-ecosystem: "github-actions"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "weekly"
|
|
||||||
|
|||||||
+38
-171
@@ -17,130 +17,49 @@ permissions:
|
|||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
|
||||||
name: Build Dev Image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 15
|
|
||||||
if: "!startsWith(github.ref, 'refs/tags/')"
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Lint Dockerfile
|
|
||||||
uses: hadolint/hadolint-action@2332a7b74a6de0dda2e2221d575162eba76ba5e5 # v3.3.0
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
|
||||||
- name: Build Docker images
|
|
||||||
uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7
|
|
||||||
with:
|
|
||||||
pull: true
|
|
||||||
files: |
|
|
||||||
compose.yaml
|
|
||||||
compose.override.yaml
|
|
||||||
set: |
|
|
||||||
*.cache-from=type=gha,scope=${{github.ref}}-devbuild
|
|
||||||
*.cache-from=type=gha,scope=refs/heads/main-devbuild
|
|
||||||
*.cache-to=type=gha,scope=${{github.ref}}-devbuild,mode=${{ github.event_name == 'pull_request' && 'min' || 'max' }}
|
|
||||||
|
|
||||||
quality:
|
|
||||||
name: Code Quality
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 20
|
|
||||||
needs: build
|
|
||||||
if: "!startsWith(github.ref, 'refs/tags/')"
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
|
||||||
- name: Load Docker images
|
|
||||||
uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7
|
|
||||||
with:
|
|
||||||
load: true
|
|
||||||
files: |
|
|
||||||
compose.yaml
|
|
||||||
compose.override.yaml
|
|
||||||
set: |
|
|
||||||
*.cache-from=type=gha,scope=${{github.ref}}-devbuild
|
|
||||||
- name: Start services
|
|
||||||
run: docker compose up php database --wait --no-build
|
|
||||||
- name: Warm up dev cache
|
|
||||||
run: docker compose exec -T php bin/console cache:warmup --env=dev
|
|
||||||
- name: Lint Twig templates
|
|
||||||
id: twig_lint
|
|
||||||
continue-on-error: true
|
|
||||||
run: docker compose exec -T php bin/console lint:twig --format=github templates
|
|
||||||
- name: Coding Style
|
|
||||||
id: cs
|
|
||||||
continue-on-error: true
|
|
||||||
run: docker compose exec -T php vendor/bin/php-cs-fixer check --diff --show-progress=none
|
|
||||||
- name: Twig Coding Style
|
|
||||||
id: twig_cs
|
|
||||||
continue-on-error: true
|
|
||||||
run: docker compose exec -T php vendor/bin/twig-cs-fixer check
|
|
||||||
- name: Static Analysis (PHPStan)
|
|
||||||
id: phpstan
|
|
||||||
continue-on-error: true
|
|
||||||
run: docker compose exec -T php vendor/bin/phpstan analyse --no-progress --no-ansi --error-format=github
|
|
||||||
- name: Rector
|
|
||||||
id: rector
|
|
||||||
continue-on-error: true
|
|
||||||
run: docker compose exec -T php vendor/bin/rector process --dry-run --no-progress-bar --output-format=github
|
|
||||||
- name: Check HTTP reachability
|
|
||||||
run: curl -v --fail-with-body http://localhost
|
|
||||||
- name: Assert all checks passed
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
failed=0
|
|
||||||
check() {
|
|
||||||
local name="$1" outcome="$2"
|
|
||||||
if [[ "$outcome" == "failure" ]]; then
|
|
||||||
echo "::error::$name failed"
|
|
||||||
failed=1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
check "Twig Lint" "${{ steps.twig_lint.outcome }}"
|
|
||||||
check "Coding Style" "${{ steps.cs.outcome }}"
|
|
||||||
check "Twig Coding Style" "${{ steps.twig_cs.outcome }}"
|
|
||||||
check "PHPStan" "${{ steps.phpstan.outcome }}"
|
|
||||||
check "Rector" "${{ steps.rector.outcome }}"
|
|
||||||
exit $failed
|
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
name: Tests
|
name: Tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 20
|
|
||||||
needs: build
|
|
||||||
if: "!startsWith(github.ref, 'refs/tags/')"
|
|
||||||
permissions:
|
permissions:
|
||||||
checks: write
|
checks: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
uses: actions/checkout@v4
|
||||||
with:
|
- name: Lint Dockerfile
|
||||||
persist-credentials: false
|
uses: hadolint/hadolint-action@v3.1.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Load Docker images
|
- name: Build Docker images
|
||||||
uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
|
pull: true
|
||||||
load: true
|
load: true
|
||||||
files: |
|
files: |
|
||||||
compose.yaml
|
compose.yaml
|
||||||
compose.override.yaml
|
compose.override.yaml
|
||||||
set: |
|
set: |
|
||||||
*.cache-from=type=gha,scope=${{github.ref}}-devbuild
|
*.cache-from=type=gha,scope=${{github.ref}}
|
||||||
|
*.cache-from=type=gha,scope=refs/heads/main
|
||||||
|
*.cache-to=type=gha,scope=${{github.ref}},mode=max
|
||||||
- name: Start services
|
- name: Start services
|
||||||
run: docker compose up php database --wait --no-build
|
run: docker compose up php database --wait --no-build
|
||||||
|
- name: Lint Twig templates
|
||||||
|
run: docker compose exec -T php bin/console lint:twig --format=github templates
|
||||||
|
- name: Coding Style
|
||||||
|
run: docker compose exec -T php vendor/bin/php-cs-fixer check --diff --show-progress=none
|
||||||
|
- name: Twig Coding Style
|
||||||
|
run: docker compose exec -T php vendor/bin/twig-cs-fixer check
|
||||||
|
- name: Static Analysis (PHPStan)
|
||||||
|
run: docker compose exec -T php vendor/bin/phpstan analyse --no-progress --no-ansi --error-format=github
|
||||||
|
- name: Rector
|
||||||
|
run: docker compose exec -T php vendor/bin/rector process --dry-run --no-progress-bar --output-format=github
|
||||||
|
- name: Check HTTP reachability
|
||||||
|
run: curl -v --fail-with-body http://localhost
|
||||||
|
- name: Check Mercure reachability
|
||||||
|
if: false
|
||||||
|
run: curl -vkI --fail-with-body https://localhost/.well-known/mercure?topic=test
|
||||||
- name: Create test database
|
- name: Create test database
|
||||||
run: docker compose exec -T php bin/console -e test doctrine:database:create
|
run: docker compose exec -T php bin/console -e test doctrine:database:create
|
||||||
- name: Run migrations
|
- name: Run migrations
|
||||||
@@ -151,78 +70,31 @@ jobs:
|
|||||||
run: docker compose exec -T php vendor/bin/phpunit --log-junit var/phpunit/junit.xml
|
run: docker compose exec -T php vendor/bin/phpunit --log-junit var/phpunit/junit.xml
|
||||||
- name: Publish PHPUnit test results
|
- name: Publish PHPUnit test results
|
||||||
if: always()
|
if: always()
|
||||||
uses: mikepenz/action-junit-report@d9f48fc87bc235f7e214acf696ca5abc0a986f16 # v6
|
uses: mikepenz/action-junit-report@v5
|
||||||
with:
|
with:
|
||||||
report_paths: var/phpunit/junit.xml
|
report_paths: var/phpunit/junit.xml
|
||||||
check_name: PHPUnit
|
check_name: PHPUnit
|
||||||
- name: Doctrine Schema Validator
|
- name: Doctrine Schema Validator
|
||||||
run: docker compose exec -T php bin/console -e test doctrine:schema:validate
|
run: docker compose exec -T php bin/console -e test doctrine:schema:validate
|
||||||
|
|
||||||
verify-prior-run:
|
|
||||||
name: Verify Prior CI Run
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 20
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
permissions:
|
|
||||||
actions: read
|
|
||||||
steps:
|
|
||||||
- name: Wait for and verify successful CI run on this commit
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ github.token }}
|
|
||||||
run: |
|
|
||||||
max_attempts=30
|
|
||||||
attempt=0
|
|
||||||
while [[ $attempt -lt $max_attempts ]]; do
|
|
||||||
attempt=$((attempt + 1))
|
|
||||||
|
|
||||||
success_count=$(gh api \
|
|
||||||
"repos/${{ github.repository }}/actions/workflows/ci.yml/runs?head_sha=${{ github.sha }}&status=success&per_page=5" \
|
|
||||||
--jq "[.workflow_runs[] | select(.id != ${{ github.run_id }})] | length")
|
|
||||||
|
|
||||||
if [[ "$success_count" -gt 0 ]]; then
|
|
||||||
echo "Found $success_count prior successful CI run(s) for ${{ github.sha }}."
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
in_progress_count=$(gh api \
|
|
||||||
"repos/${{ github.repository }}/actions/workflows/ci.yml/runs?head_sha=${{ github.sha }}&per_page=10" \
|
|
||||||
--jq "[.workflow_runs[] | select(.id != ${{ github.run_id }}) | select(.status == \"in_progress\" or .status == \"queued\" or .status == \"waiting\" or .status == \"requested\" or .status == \"pending\")] | length")
|
|
||||||
|
|
||||||
if [[ "$in_progress_count" -gt 0 ]]; then
|
|
||||||
echo "CI still in progress (attempt $attempt/$max_attempts), waiting 30s..."
|
|
||||||
sleep 30
|
|
||||||
else
|
|
||||||
echo "::error::No prior successful CI run found for ${{ github.sha }}. Only tag commits that have passed CI on main."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "::error::Timed out waiting for CI run to complete for ${{ github.sha }}."
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
build-deploy:
|
build-deploy:
|
||||||
name: Build and Deploy
|
name: Build and deploy to ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }}
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
environment:
|
environment:
|
||||||
name: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || 'acceptance' }}
|
name: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }}
|
||||||
url: ${{ vars.URL }}
|
url: ${{ vars.URL }}
|
||||||
needs: [quality, tests, verify-prior-run]
|
needs: tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
if: (github.ref == 'refs/heads/main' && false) || startsWith(github.ref, 'refs/tags/')
|
||||||
if: >-
|
|
||||||
always() && !cancelled() && !failure() &&
|
|
||||||
((github.ref == 'refs/heads/main' && false) || startsWith(github.ref, 'refs/tags/'))
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Log in to GitHub Container Registry
|
- name: Log in to GitHub Container Registry
|
||||||
uses: docker/login-action@c99871dec2022cc055c062a10cc1a1310835ceb4 # v4
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
@@ -234,23 +106,20 @@ jobs:
|
|||||||
REPO_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
|
REPO_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
|
||||||
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||||
TAG="${GITHUB_REF#refs/tags/}"
|
TAG="${GITHUB_REF#refs/tags/}"
|
||||||
SENTRY_VERSION="${TAG#v}"
|
|
||||||
{
|
{
|
||||||
echo "tag=$TAG"
|
echo "tag=$TAG"
|
||||||
echo "sentry_version=$SENTRY_VERSION"
|
|
||||||
echo "full_name=ghcr.io/${REPO_LOWER}:$TAG"
|
echo "full_name=ghcr.io/${REPO_LOWER}:$TAG"
|
||||||
} >> "$GITHUB_OUTPUT"
|
} >> "$GITHUB_OUTPUT"
|
||||||
else
|
else
|
||||||
SHORT_SHA=$(git rev-parse --short HEAD)
|
SHORT_SHA=$(git rev-parse --short HEAD)
|
||||||
{
|
{
|
||||||
echo "tag=$SHORT_SHA"
|
echo "tag=$SHORT_SHA"
|
||||||
echo "sentry_version=$SHORT_SHA"
|
|
||||||
echo "full_name=ghcr.io/${REPO_LOWER}:$SHORT_SHA"
|
echo "full_name=ghcr.io/${REPO_LOWER}:$SHORT_SHA"
|
||||||
} >> "$GITHUB_OUTPUT"
|
} >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Build and Push Docker images
|
- name: Build and Push Docker images
|
||||||
uses: docker/bake-action@d3418bd7d0e9324001bca92fa8ba175ea7e6dc9b # v7
|
uses: docker/bake-action@v5
|
||||||
with:
|
with:
|
||||||
pull: true
|
pull: true
|
||||||
push: true
|
push: true
|
||||||
@@ -264,20 +133,18 @@ jobs:
|
|||||||
*.tags=${{ steps.meta.outputs.full_name }}
|
*.tags=${{ steps.meta.outputs.full_name }}
|
||||||
|
|
||||||
- name: Create Sentry release
|
- name: Create Sentry release
|
||||||
uses: getsentry/action-release@ff07929a6537bac57790c3451cf4d364aca38528 # v3
|
uses: getsentry/action-release@v3
|
||||||
env:
|
env:
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
|
||||||
with:
|
with:
|
||||||
release: ${{steps.meta.outputs.sentry_version}}
|
release: ${{steps.meta.outputs.tag}}
|
||||||
environment: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || 'acceptance' }}
|
environment: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }}
|
||||||
|
|
||||||
- name: Trigger Portainer Deployment
|
- name: Trigger Portainer Deployment
|
||||||
shell: bash
|
shell: bash
|
||||||
env:
|
env:
|
||||||
PORTAINER_WEBHOOK: ${{secrets.PORTAINER_WEBHOOK}}
|
PORTAINER_WEBHOOK: ${{secrets.PORTAINER_WEBHOOK}}
|
||||||
IMAGE_TAG: ${{steps.meta.outputs.tag}}
|
|
||||||
SENTRY_RELEASE: ${{steps.meta.outputs.sentry_version}}
|
|
||||||
run: |
|
run: |
|
||||||
curl -v -X POST "${PORTAINER_WEBHOOK}?IMAGE_TAG=${IMAGE_TAG}&SENTRY_RELEASE=${SENTRY_RELEASE}" --fail-with-body
|
curl -v -X POST "$PORTAINER_WEBHOOK"?IMAGE_TAG=${{steps.meta.outputs.tag}} --fail-with-body
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Dependabot metadata
|
- name: Dependabot metadata
|
||||||
id: metadata
|
id: metadata
|
||||||
uses: dependabot/fetch-metadata@v3
|
uses: dependabot/fetch-metadata@v2
|
||||||
with:
|
with:
|
||||||
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
github-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
- name: Enable auto-merge for Dependabot PRs
|
- name: Enable auto-merge for Dependabot PRs
|
||||||
|
|||||||
Generated
-1
@@ -169,7 +169,6 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/git-state" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/git-state" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/ergebnis/agent-detector" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/ergebnis/agent-detector" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-deepclone" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-deepclone" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/file-filter" />
|
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
Generated
+146
-145
@@ -41,169 +41,170 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="PhpIncludePathManager">
|
<component name="PhpIncludePathManager">
|
||||||
<include_path>
|
<include_path>
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/cache" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/gedmo/doctrine-extensions" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/twig/twig" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/stream" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/promise" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/event-loop" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/cache" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/clue/ndjson-react" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/psr/clock" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/twig/intl-extra" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/dama/doctrine-test-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/stof/doctrine-extensions-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-symfony" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-phpunit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-doctrine" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/child-process" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/jean85/pretty-package-versions" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/dns" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/react/socket" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sentry/sentry" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/staabm/side-effects-detector" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/rector/rector" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sentry/sentry-symfony" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/form" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-deepclone" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/ux-turbo" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/extension-installer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/asset-mapper" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/uid" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/brevo-mailer" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/phpunit-bridge" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/security-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
|
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
|
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/config" />
|
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
|
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
<path value="$PROJECT_DIR$/vendor/symfony/security-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
|
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/web-profiler-bundle" />
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
|
<path value="$PROJECT_DIR$/vendor/symfony/ux-turbo" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
|
<path value="$PROJECT_DIR$/vendor/symfony/form" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
|
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
|
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
|
<path value="$PROJECT_DIR$/vendor/symfony/brevo-mailer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
|
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
|
<path value="$PROJECT_DIR$/vendor/symfony/phpunit-bridge" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
|
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
|
<path value="$PROJECT_DIR$/vendor/symfony/config" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
|
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
|
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/type-info" />
|
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
|
<path value="$PROJECT_DIR$/vendor/symfony/asset-mapper" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
|
<path value="$PROJECT_DIR$/vendor/symfony/uid" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
|
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
|
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
|
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
|
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
|
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
<path value="$PROJECT_DIR$/vendor/symfony/psr-http-message-bridge" />
|
||||||
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
<path value="$PROJECT_DIR$/vendor/symfony/web-profiler-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
|
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
|
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
|
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
|
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
|
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
|
<path value="$PROJECT_DIR$/vendor/symfony/type-info" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
|
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/string" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/process" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
|
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
|
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
|
<path value="$PROJECT_DIR$/vendor/symfony/console" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/ergebnis/agent-detector" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/evenement/evenement" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/markbaker/complex" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
|
||||||
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/file-filter" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/git-state" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
|
||||||
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
|
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
|
||||||
<path value="$PROJECT_DIR$/vendor/thecodingmachine/safe" />
|
<path value="$PROJECT_DIR$/vendor/maennchen/zipstream-php" />
|
||||||
<path value="$PROJECT_DIR$/vendor/thecodingmachine/phpstan-safe-rule" />
|
<path value="$PROJECT_DIR$/vendor/evenement/evenement" />
|
||||||
<path value="$PROJECT_DIR$/vendor/vincentlanglet/twig-cs-fixer" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
|
||||||
<path value="$PROJECT_DIR$/vendor/martin-georgiev/postgresql-for-doctrine" />
|
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
|
||||||
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
|
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
|
||||||
<path value="$PROJECT_DIR$/vendor/symfonycasts/verify-email-bundle" />
|
<path value="$PROJECT_DIR$/vendor/phpoffice/phpspreadsheet" />
|
||||||
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
|
<path value="$PROJECT_DIR$/vendor/markbaker/matrix" />
|
||||||
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
|
<path value="$PROJECT_DIR$/vendor/markbaker/complex" />
|
||||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
|
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
|
||||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/symfonycasts/sass-bundle" />
|
|
||||||
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
|
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfonycasts/sass-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfonycasts/verify-email-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/thecodingmachine/safe" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/martin-georgiev/postgresql-for-doctrine" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/vincentlanglet/twig-cs-fixer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/friendsofphp/php-cs-fixer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/thecodingmachine/phpstan-safe-rule" />
|
||||||
<path value="$PROJECT_DIR$/vendor/composer" />
|
<path value="$PROJECT_DIR$/vendor/composer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/log" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/container" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/clue/ndjson-react" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/clock" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/simple-cache" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/psr/cache" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/promise" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/stream" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/cache" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/event-loop" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/jean85/pretty-package-versions" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/child-process" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/socket" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/react/dns" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/twig/intl-extra" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/stof/doctrine-extensions-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/dama/doctrine-test-bundle" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/gedmo/doctrine-extensions" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/fidry/cpu-core-counter" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/twig/twig" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-phpunit" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-symfony" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan-doctrine" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/phpstan" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phpstan/extension-installer" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/staabm/side-effects-detector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sentry/sentry" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sentry/sentry-symfony" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/rector/rector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php85" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/sebastian/git-state" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/ergebnis/agent-detector" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-deepclone" />
|
||||||
</include_path>
|
</include_path>
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpInterpreters">
|
<component name="PhpInterpreters">
|
||||||
|
|||||||
+3
-83
@@ -1,97 +1,17 @@
|
|||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-image: url("../img/background.png");
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-color: black;
|
|
||||||
color: white;
|
|
||||||
display: grid;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
height: 100%;
|
min-height: 100%;
|
||||||
background-image: url("../img/background.png");
|
background-image: url("../img/background.png");
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-color: black;
|
background-color: black;
|
||||||
display: grid;
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quiz-form-narrow {
|
|
||||||
max-width: 320px;
|
|
||||||
width: 100%;
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quiz-content {
|
|
||||||
width: fit-content;
|
|
||||||
max-width: min(760px, 100%);
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quiz-answers-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, auto);
|
|
||||||
column-gap: 2rem;
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.answer-btn {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.8rem;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 1.1rem;
|
|
||||||
padding: 0.4rem 0;
|
|
||||||
cursor: pointer;
|
|
||||||
text-align: left;
|
|
||||||
line-height: 1.3;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 2rem;
|
|
||||||
height: 2rem;
|
|
||||||
background: radial-gradient(ellipse at 35% 30%, #6abf4b, #2d7a1f);
|
|
||||||
border-radius: 4px;
|
|
||||||
box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.25), 0 2px 6px rgba(0, 0, 0, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
color: #7ed45a;
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: radial-gradient(ellipse at 35% 30%, #86d45f, #3d9c2a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input.btn-check:checked + label.answer-btn {
|
|
||||||
color: #7ed45a;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
background: radial-gradient(ellipse at 35% 30%, #86d45f, #3d9c2a);
|
|
||||||
box-shadow: 0 0 10px rgba(106, 191, 75, 0.7), inset 0 1px 2px rgba(255, 255, 255, 0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.quiz-topbar {
|
|
||||||
position: fixed;
|
|
||||||
top: 1rem;
|
|
||||||
right: 1rem;
|
|
||||||
z-index: 1030;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.elimination-screen {
|
.elimination-screen {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ services:
|
|||||||
target: frankenphp_dev
|
target: frankenphp_dev
|
||||||
volumes:
|
volumes:
|
||||||
- ./:/app
|
- ./:/app
|
||||||
- ~/.composer/cache:/root/.composer/cache
|
|
||||||
- ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro
|
- ./frankenphp/Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
- ./frankenphp/conf.d/20-app.dev.ini:/usr/local/etc/php/app.conf.d/20-app.dev.ini:ro
|
- ./frankenphp/conf.d/20-app.dev.ini:/usr/local/etc/php/app.conf.d/20-app.dev.ini:ro
|
||||||
- ./frankenphp/data:/data
|
- ./frankenphp/data:/data
|
||||||
@@ -47,8 +46,6 @@ services:
|
|||||||
- sass:build
|
- sass:build
|
||||||
- --watch
|
- --watch
|
||||||
- -v
|
- -v
|
||||||
healthcheck:
|
|
||||||
disable: true
|
|
||||||
|
|
||||||
###> symfony/mercure-bundle ###
|
###> symfony/mercure-bundle ###
|
||||||
###< symfony/mercure-bundle ###
|
###< symfony/mercure-bundle ###
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ services:
|
|||||||
MAILER_DSN: ${MAILER_DSN}
|
MAILER_DSN: ${MAILER_DSN}
|
||||||
MAILER_SENDER: ${MAILER_SENDER}
|
MAILER_SENDER: ${MAILER_SENDER}
|
||||||
SENTRY_DSN: ${SENTRY_DSN}
|
SENTRY_DSN: ${SENTRY_DSN}
|
||||||
SENTRY_RELEASE: ${SENTRY_RELEASE}
|
SENTRY_RELEASE: ${IMAGE_TAG}
|
||||||
SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT}
|
SENTRY_ENVIRONMENT: ${SENTRY_ENVIRONMENT}
|
||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
|
|||||||
Generated
+79
-81
@@ -1839,16 +1839,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "martin-georgiev/postgresql-for-doctrine",
|
"name": "martin-georgiev/postgresql-for-doctrine",
|
||||||
"version": "v4.7.0",
|
"version": "v4.6.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/martin-georgiev/postgresql-for-doctrine.git",
|
"url": "https://github.com/martin-georgiev/postgresql-for-doctrine.git",
|
||||||
"reference": "23b5c2694083355ab87eaa913b43a0cddd8c64bb"
|
"reference": "59841c7e53f8339b13bc0cb0ee9931b7b9bbb139"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/martin-georgiev/postgresql-for-doctrine/zipball/23b5c2694083355ab87eaa913b43a0cddd8c64bb",
|
"url": "https://api.github.com/repos/martin-georgiev/postgresql-for-doctrine/zipball/59841c7e53f8339b13bc0cb0ee9931b7b9bbb139",
|
||||||
"reference": "23b5c2694083355ab87eaa913b43a0cddd8c64bb",
|
"reference": "59841c7e53f8339b13bc0cb0ee9931b7b9bbb139",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -1863,13 +1863,13 @@
|
|||||||
"deptrac/deptrac": "^4.0",
|
"deptrac/deptrac": "^4.0",
|
||||||
"doctrine/orm": "~2.14||~3.0",
|
"doctrine/orm": "~2.14||~3.0",
|
||||||
"ekino/phpstan-banned-code": "^3.2.0",
|
"ekino/phpstan-banned-code": "^3.2.0",
|
||||||
"friendsofphp/php-cs-fixer": "^3.95.11",
|
"friendsofphp/php-cs-fixer": "^3.95.2",
|
||||||
"phpstan/phpstan": "^2.2.2",
|
"phpstan/phpstan": "^2.1.55",
|
||||||
"phpstan/phpstan-deprecation-rules": "^2.0.4",
|
"phpstan/phpstan-deprecation-rules": "^2.0.4",
|
||||||
"phpstan/phpstan-doctrine": "^2.0.27",
|
"phpstan/phpstan-doctrine": "^2.0.22",
|
||||||
"phpstan/phpstan-phpunit": "^2.0.16",
|
"phpstan/phpstan-phpunit": "^2.0.16",
|
||||||
"phpunit/phpunit": "^10.5.63||^11.5",
|
"phpunit/phpunit": "^10.5.63||^11.5",
|
||||||
"rector/rector": "^2.5.2",
|
"rector/rector": "^2.4.4",
|
||||||
"symfony/cache": "^6.4||^7.0",
|
"symfony/cache": "^6.4||^7.0",
|
||||||
"symfony/var-exporter": "^6.4||^7.0"
|
"symfony/var-exporter": "^6.4||^7.0"
|
||||||
},
|
},
|
||||||
@@ -1952,7 +1952,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/martin-georgiev/postgresql-for-doctrine/issues",
|
"issues": "https://github.com/martin-georgiev/postgresql-for-doctrine/issues",
|
||||||
"source": "https://github.com/martin-georgiev/postgresql-for-doctrine/tree/v4.7.0"
|
"source": "https://github.com/martin-georgiev/postgresql-for-doctrine/tree/v4.6.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -1964,7 +1964,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-07-01T18:17:39+00:00"
|
"time": "2026-05-29T19:11:20+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-common",
|
"name": "phpdocumentor/reflection-common",
|
||||||
@@ -9287,16 +9287,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "friendsofphp/php-cs-fixer",
|
"name": "friendsofphp/php-cs-fixer",
|
||||||
"version": "v3.95.11",
|
"version": "v3.95.8",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
|
||||||
"reference": "35f98e1293283397824d7f349ce5afb8747c3cd5"
|
"reference": "4140023f552ff02346df9b1329742532166f677f"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/35f98e1293283397824d7f349ce5afb8747c3cd5",
|
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/4140023f552ff02346df9b1329742532166f677f",
|
||||||
"reference": "35f98e1293283397824d7f349ce5afb8747c3cd5",
|
"reference": "4140023f552ff02346df9b1329742532166f677f",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -9330,7 +9330,7 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"facile-it/paraunit": "^1.3.1 || ^2.11.0",
|
"facile-it/paraunit": "^1.3.1 || ^2.11.0",
|
||||||
"infection/infection": "^0.32.7",
|
"infection/infection": "^0.32.7",
|
||||||
"justinrainbow/json-schema": "^6.10.0",
|
"justinrainbow/json-schema": "^6.9.0",
|
||||||
"keradus/cli-executor": "^2.3",
|
"keradus/cli-executor": "^2.3",
|
||||||
"mikey179/vfsstream": "^1.6.12",
|
"mikey179/vfsstream": "^1.6.12",
|
||||||
"php-coveralls/php-coveralls": "^2.9.1",
|
"php-coveralls/php-coveralls": "^2.9.1",
|
||||||
@@ -9380,7 +9380,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
|
||||||
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.11"
|
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.8"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -9388,7 +9388,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-25T14:17:04+00:00"
|
"time": "2026-06-16T09:52:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "myclabs/deep-copy",
|
"name": "myclabs/deep-copy",
|
||||||
@@ -9676,11 +9676,11 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan",
|
"name": "phpstan/phpstan",
|
||||||
"version": "2.2.4",
|
"version": "2.2.2",
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/f0fe3fb03bb53ce68cc2416785b260e62226ec27",
|
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
|
||||||
"reference": "f0fe3fb03bb53ce68cc2416785b260e62226ec27",
|
"reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -9736,7 +9736,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-07-03T07:00:23+00:00"
|
"time": "2026-06-05T09:00:01+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-doctrine",
|
"name": "phpstan/phpstan-doctrine",
|
||||||
@@ -9817,22 +9817,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-phpunit",
|
"name": "phpstan/phpstan-phpunit",
|
||||||
"version": "2.0.17",
|
"version": "2.0.16",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
"url": "https://github.com/phpstan/phpstan-phpunit.git",
|
||||||
"reference": "c2f977551f0736d60467b3d754b2e0cf4e337b3f"
|
"reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/c2f977551f0736d60467b3d754b2e0cf4e337b3f",
|
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/6ab598e1bc106e6827fd346ae4a12b4a5d634c32",
|
||||||
"reference": "c2f977551f0736d60467b3d754b2e0cf4e337b3f",
|
"reference": "6ab598e1bc106e6827fd346ae4a12b4a5d634c32",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"phar-io/version": "^3.2",
|
|
||||||
"php": "^7.4 || ^8.0",
|
"php": "^7.4 || ^8.0",
|
||||||
"phpstan/phpstan": "^2.2.3"
|
"phpstan/phpstan": "^2.1.32"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"phpunit/phpunit": "<7.0"
|
"phpunit/phpunit": "<7.0"
|
||||||
@@ -9842,8 +9841,7 @@
|
|||||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||||
"phpstan/phpstan-deprecation-rules": "^2.0",
|
"phpstan/phpstan-deprecation-rules": "^2.0",
|
||||||
"phpstan/phpstan-strict-rules": "^2.0",
|
"phpstan/phpstan-strict-rules": "^2.0",
|
||||||
"phpunit/phpunit": "^9.6",
|
"phpunit/phpunit": "^9.6"
|
||||||
"shipmonk/name-collision-detector": "^2.1"
|
|
||||||
},
|
},
|
||||||
"type": "phpstan-extension",
|
"type": "phpstan-extension",
|
||||||
"extra": {
|
"extra": {
|
||||||
@@ -9869,9 +9867,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
|
||||||
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.17"
|
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.16"
|
||||||
},
|
},
|
||||||
"time": "2026-06-29T05:32:23+00:00"
|
"time": "2026-02-14T09:05:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpstan/phpstan-symfony",
|
"name": "phpstan/phpstan-symfony",
|
||||||
@@ -10332,16 +10330,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "13.2.2",
|
"version": "13.2.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "492c067e618de7b3c76105082c90f9d2833401b7"
|
"reference": "60da0ff1e10a0f72ee18a24117ec3b613a346bba"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/492c067e618de7b3c76105082c90f9d2833401b7",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/60da0ff1e10a0f72ee18a24117ec3b613a346bba",
|
||||||
"reference": "492c067e618de7b3c76105082c90f9d2833401b7",
|
"reference": "60da0ff1e10a0f72ee18a24117ec3b613a346bba",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -10412,7 +10410,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/13.2.2"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/13.2.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -10420,7 +10418,7 @@
|
|||||||
"type": "other"
|
"type": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-29T13:36:29+00:00"
|
"time": "2026-06-15T13:14:22+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "react/cache",
|
"name": "react/cache",
|
||||||
@@ -10950,16 +10948,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
"version": "2.5.2",
|
"version": "2.4.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rectorphp/rector.git",
|
"url": "https://github.com/rectorphp/rector.git",
|
||||||
"reference": "49ff6339174bdbdf50b0b35ecbcff14a05ac9e24"
|
"reference": "9b9e5c76618e4d359f65b54ca2eabcad3d1761ee"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/49ff6339174bdbdf50b0b35ecbcff14a05ac9e24",
|
"url": "https://api.github.com/repos/rectorphp/rector/zipball/9b9e5c76618e4d359f65b54ca2eabcad3d1761ee",
|
||||||
"reference": "49ff6339174bdbdf50b0b35ecbcff14a05ac9e24",
|
"reference": "9b9e5c76618e4d359f65b54ca2eabcad3d1761ee",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -10998,7 +10996,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/rectorphp/rector/issues",
|
"issues": "https://github.com/rectorphp/rector/issues",
|
||||||
"source": "https://github.com/rectorphp/rector/tree/2.5.2"
|
"source": "https://github.com/rectorphp/rector/tree/2.4.6"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -11006,7 +11004,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-22T11:39:33+00:00"
|
"time": "2026-06-17T11:56:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
@@ -12169,16 +12167,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/browser-kit",
|
"name": "symfony/browser-kit",
|
||||||
"version": "v8.1.1",
|
"version": "v8.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/browser-kit.git",
|
"url": "https://github.com/symfony/browser-kit.git",
|
||||||
"reference": "f2ac86001ca9f487e8c6d0e11c8e33e6a9b8b2d5"
|
"reference": "74e18e582cdda0eca35f7c74e1e48e62f0ede853"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/f2ac86001ca9f487e8c6d0e11c8e33e6a9b8b2d5",
|
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/74e18e582cdda0eca35f7c74e1e48e62f0ede853",
|
||||||
"reference": "f2ac86001ca9f487e8c6d0e11c8e33e6a9b8b2d5",
|
"reference": "74e18e582cdda0eca35f7c74e1e48e62f0ede853",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12217,7 +12215,7 @@
|
|||||||
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
|
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/browser-kit/tree/v8.1.1"
|
"source": "https://github.com/symfony/browser-kit/tree/v8.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -12237,7 +12235,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-09T10:54:51+00:00"
|
"time": "2026-05-29T05:06:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/css-selector",
|
"name": "symfony/css-selector",
|
||||||
@@ -12310,16 +12308,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/dom-crawler",
|
"name": "symfony/dom-crawler",
|
||||||
"version": "v8.1.1",
|
"version": "v8.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/dom-crawler.git",
|
"url": "https://github.com/symfony/dom-crawler.git",
|
||||||
"reference": "1dfadd25537c8fcb6752cce5775f24647d976bdc"
|
"reference": "77ca351474ea018daba5f2e473cbf1b9b8e72ac6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1dfadd25537c8fcb6752cce5775f24647d976bdc",
|
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/77ca351474ea018daba5f2e473cbf1b9b8e72ac6",
|
||||||
"reference": "1dfadd25537c8fcb6752cce5775f24647d976bdc",
|
"reference": "77ca351474ea018daba5f2e473cbf1b9b8e72ac6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12356,7 +12354,7 @@
|
|||||||
"description": "Eases DOM navigation for HTML and XML documents",
|
"description": "Eases DOM navigation for HTML and XML documents",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/dom-crawler/tree/v8.1.1"
|
"source": "https://github.com/symfony/dom-crawler/tree/v8.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -12376,7 +12374,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-05-29T05:06:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/maker-bundle",
|
"name": "symfony/maker-bundle",
|
||||||
@@ -12479,16 +12477,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/phpunit-bridge",
|
"name": "symfony/phpunit-bridge",
|
||||||
"version": "v8.1.1",
|
"version": "v8.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/phpunit-bridge.git",
|
"url": "https://github.com/symfony/phpunit-bridge.git",
|
||||||
"reference": "3e1c9a9167e07474ec115555b632f0ffadb0f94d"
|
"reference": "1fed488f8033f2dece371e60a1c66f2add274916"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/3e1c9a9167e07474ec115555b632f0ffadb0f94d",
|
"url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/1fed488f8033f2dece371e60a1c66f2add274916",
|
||||||
"reference": "3e1c9a9167e07474ec115555b632f0ffadb0f94d",
|
"reference": "1fed488f8033f2dece371e60a1c66f2add274916",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12540,7 +12538,7 @@
|
|||||||
"testing"
|
"testing"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/phpunit-bridge/tree/v8.1.1"
|
"source": "https://github.com/symfony/phpunit-bridge/tree/v8.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -12560,20 +12558,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-09T10:54:51+00:00"
|
"time": "2026-05-29T05:06:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/web-profiler-bundle",
|
"name": "symfony/web-profiler-bundle",
|
||||||
"version": "v8.1.1",
|
"version": "v8.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/web-profiler-bundle.git",
|
"url": "https://github.com/symfony/web-profiler-bundle.git",
|
||||||
"reference": "eb4cf71d8fc496d790ec85b1b684a7ac30d57a96"
|
"reference": "f8ccea08797a511b85a698b0da40e1b9e6461086"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/eb4cf71d8fc496d790ec85b1b684a7ac30d57a96",
|
"url": "https://api.github.com/repos/symfony/web-profiler-bundle/zipball/f8ccea08797a511b85a698b0da40e1b9e6461086",
|
||||||
"reference": "eb4cf71d8fc496d790ec85b1b684a7ac30d57a96",
|
"reference": "f8ccea08797a511b85a698b0da40e1b9e6461086",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12625,7 +12623,7 @@
|
|||||||
"dev"
|
"dev"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/web-profiler-bundle/tree/v8.1.1"
|
"source": "https://github.com/symfony/web-profiler-bundle/tree/v8.1.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -12645,27 +12643,27 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-05T06:23:12+00:00"
|
"time": "2026-05-29T05:06:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "thecodingmachine/phpstan-safe-rule",
|
"name": "thecodingmachine/phpstan-safe-rule",
|
||||||
"version": "v1.4.7",
|
"version": "v1.4.3",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thecodingmachine/phpstan-safe-rule.git",
|
"url": "https://github.com/thecodingmachine/phpstan-safe-rule.git",
|
||||||
"reference": "51fa2a35a270f683fc9ea53384a03e892b4d7b51"
|
"reference": "5c804889253ce9498ef185e108e9f94b6023208e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thecodingmachine/phpstan-safe-rule/zipball/51fa2a35a270f683fc9ea53384a03e892b4d7b51",
|
"url": "https://api.github.com/repos/thecodingmachine/phpstan-safe-rule/zipball/5c804889253ce9498ef185e108e9f94b6023208e",
|
||||||
"reference": "51fa2a35a270f683fc9ea53384a03e892b4d7b51",
|
"reference": "5c804889253ce9498ef185e108e9f94b6023208e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"nikic/php-parser": "^5",
|
"nikic/php-parser": "^5",
|
||||||
"php": "^8.1",
|
"php": "^8.1",
|
||||||
"phpstan/phpstan": "^2.2.2",
|
"phpstan/phpstan": "^2.1.11",
|
||||||
"thecodingmachine/safe": "^3.1"
|
"thecodingmachine/safe": "^1.2 || ^2.0 || ^3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"php-coveralls/php-coveralls": "^2.1",
|
"php-coveralls/php-coveralls": "^2.1",
|
||||||
@@ -12701,9 +12699,9 @@
|
|||||||
"description": "A PHPStan rule to detect safety issues. Must be used in conjunction with thecodingmachine/safe",
|
"description": "A PHPStan rule to detect safety issues. Must be used in conjunction with thecodingmachine/safe",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/thecodingmachine/phpstan-safe-rule/issues",
|
"issues": "https://github.com/thecodingmachine/phpstan-safe-rule/issues",
|
||||||
"source": "https://github.com/thecodingmachine/phpstan-safe-rule/tree/v1.4.7"
|
"source": "https://github.com/thecodingmachine/phpstan-safe-rule/tree/v1.4.3"
|
||||||
},
|
},
|
||||||
"time": "2026-06-21T07:55:55+00:00"
|
"time": "2025-11-21T09:41:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "theseer/tokenizer",
|
"name": "theseer/tokenizer",
|
||||||
@@ -12757,16 +12755,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "vincentlanglet/twig-cs-fixer",
|
"name": "vincentlanglet/twig-cs-fixer",
|
||||||
"version": "4.0.2",
|
"version": "4.0.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/VincentLanglet/Twig-CS-Fixer.git",
|
"url": "https://github.com/VincentLanglet/Twig-CS-Fixer.git",
|
||||||
"reference": "1cb75618f7dd0f9bf51924aa6d3aa8c588f51d5a"
|
"reference": "366f7cca494a6f95c5f410ae542aef9c164d329e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/1cb75618f7dd0f9bf51924aa6d3aa8c588f51d5a",
|
"url": "https://api.github.com/repos/VincentLanglet/Twig-CS-Fixer/zipball/366f7cca494a6f95c5f410ae542aef9c164d329e",
|
||||||
"reference": "1cb75618f7dd0f9bf51924aa6d3aa8c588f51d5a",
|
"reference": "366f7cca494a6f95c5f410ae542aef9c164d329e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -12822,7 +12820,7 @@
|
|||||||
"homepage": "https://github.com/VincentLanglet/Twig-CS-Fixer",
|
"homepage": "https://github.com/VincentLanglet/Twig-CS-Fixer",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/VincentLanglet/Twig-CS-Fixer/issues",
|
"issues": "https://github.com/VincentLanglet/Twig-CS-Fixer/issues",
|
||||||
"source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/4.0.2"
|
"source": "https://github.com/VincentLanglet/Twig-CS-Fixer/tree/4.0.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -12830,7 +12828,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2026-06-29T15:22:14+00:00"
|
"time": "2026-06-18T15:31:27+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ when@dev:
|
|||||||
framework:
|
framework:
|
||||||
profiler:
|
profiler:
|
||||||
only_exceptions: false
|
only_exceptions: false
|
||||||
|
collect_serializer_data: true
|
||||||
|
|
||||||
when@test:
|
when@test:
|
||||||
web_profiler:
|
web_profiler:
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@
|
|||||||
failOnNotice="true"
|
failOnNotice="true"
|
||||||
failOnWarning="true"
|
failOnWarning="true"
|
||||||
bootstrap="tests/bootstrap.php"
|
bootstrap="tests/bootstrap.php"
|
||||||
cacheDirectory="/tmp/phpunit.cache"
|
cacheDirectory=".phpunit.cache"
|
||||||
>
|
>
|
||||||
<php>
|
<php>
|
||||||
<ini name="display_errors" value="1" />
|
<ini name="display_errors" value="1" />
|
||||||
|
|||||||
+1
-4
@@ -3,7 +3,6 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use Rector\Config\RectorConfig;
|
use Rector\Config\RectorConfig;
|
||||||
use Rector\PHPUnit\CodeQuality\Rector\Class_\AddSeeTestAnnotationRector;
|
|
||||||
use Rector\Symfony\Bridge\Symfony\Routing\SymfonyRoutesProvider;
|
use Rector\Symfony\Bridge\Symfony\Routing\SymfonyRoutesProvider;
|
||||||
use Rector\Symfony\Contract\Bridge\Symfony\Routing\SymfonyRoutesProviderInterface;
|
use Rector\Symfony\Contract\Bridge\Symfony\Routing\SymfonyRoutesProviderInterface;
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ return RectorConfig::configure()
|
|||||||
__DIR__.'/src',
|
__DIR__.'/src',
|
||||||
__DIR__.'/tests',
|
__DIR__.'/tests',
|
||||||
])
|
])
|
||||||
->withSkipPath(__DIR__.'/config/reference.php')
|
->withSkip([__DIR__.'/config/reference.php'])
|
||||||
->withSymfonyContainerXml(__DIR__.'/var/cache/dev/Tvdt_KernelDevDebugContainer.xml')
|
->withSymfonyContainerXml(__DIR__.'/var/cache/dev/Tvdt_KernelDevDebugContainer.xml')
|
||||||
->withSymfonyContainerPhp(__DIR__.'/tests/symfony-container.php')
|
->withSymfonyContainerPhp(__DIR__.'/tests/symfony-container.php')
|
||||||
->registerService(SymfonyRoutesProvider::class, SymfonyRoutesProviderInterface::class)
|
->registerService(SymfonyRoutesProvider::class, SymfonyRoutesProviderInterface::class)
|
||||||
@@ -35,6 +34,4 @@ return RectorConfig::configure()
|
|||||||
)
|
)
|
||||||
->withAttributesSets(all: true)
|
->withAttributesSets(all: true)
|
||||||
->withComposerBased(twig: true, doctrine: true, phpunit: true, symfony: true)
|
->withComposerBased(twig: true, doctrine: true, phpunit: true, symfony: true)
|
||||||
->withSkip([AddSeeTestAnnotationRector::class])
|
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ namespace Tvdt\Controller\Backoffice;
|
|||||||
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
use Symfony\Component\HttpFoundation\HeaderUtils;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
@@ -94,7 +93,7 @@ final class BackofficeController extends AbstractController
|
|||||||
{
|
{
|
||||||
$response = new StreamedResponse($this->excel->quizToXlsx($quiz));
|
$response = new StreamedResponse($this->excel->quizToXlsx($quiz));
|
||||||
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
$response->headers->set('Content-Disposition', HeaderUtils::makeDisposition(HeaderUtils::DISPOSITION_ATTACHMENT, $quiz->name.'.xlsx'));
|
$response->headers->set('Content-Disposition', 'attachment; filename="'.$quiz->name.'.xlsx"');
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tvdt\Service;
|
namespace Tvdt\Service;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader;
|
use PhpOffice\PhpSpreadsheet\Reader;
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||||
use PhpOffice\PhpSpreadsheet\Writer;
|
use PhpOffice\PhpSpreadsheet\Writer;
|
||||||
@@ -18,40 +17,39 @@ class QuizSpreadsheetService
|
|||||||
{
|
{
|
||||||
public function generateTemplate(bool $fillExample = true): \Closure
|
public function generateTemplate(bool $fillExample = true): \Closure
|
||||||
{
|
{
|
||||||
$quiz = new Quiz();
|
$spreadsheet = new Spreadsheet();
|
||||||
|
|
||||||
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
|
$sheet->getStyle('1:1')->getFont()->setBold(true);
|
||||||
|
|
||||||
|
$sheet->setCellValue('A1', 'Question');
|
||||||
|
$sheet->getColumnDimension('A')->setWidth(30);
|
||||||
|
$sheet->getStyle('A:A')->getAlignment()->setWrapText(true);
|
||||||
|
|
||||||
|
$counter = 1;
|
||||||
|
foreach (range('B', 'L', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Answer '.$counter++);
|
||||||
|
$sheet->getColumnDimension($column)->setWidth(30);
|
||||||
|
$sheet->getStyle($column.':'.$column)->getAlignment()->setWrapText(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (range('C', 'M', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Correct');
|
||||||
|
$sheet->getColumnDimension($column)->setAutoSize(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ($fillExample) {
|
if ($fillExample) {
|
||||||
$geslacht = new Question();
|
$sheet->setCellValue('B2', 'Man');
|
||||||
$geslacht->question = 'Is de mol een man of een vrouw?';
|
$sheet->setCellValue('C2', true);
|
||||||
$geslacht->ordering = 1;
|
|
||||||
$geslacht->addAnswer(new Answer('Man', true));
|
|
||||||
$geslacht->addAnswer(new Answer('Vrouw'));
|
|
||||||
$quiz->addQuestion($geslacht);
|
|
||||||
|
|
||||||
$identiteit = new Question();
|
$sheet->setCellValue('D2', 'Vrouw');
|
||||||
$identiteit->question = 'Wie is de mol?';
|
$sheet->setCellValue('E2', false);
|
||||||
$identiteit->ordering = 2;
|
|
||||||
foreach ([
|
$sheet->setCellValue('A2', 'Is de mol een man of een vrouw?');
|
||||||
['Emma', false],
|
|
||||||
['Jan', false],
|
|
||||||
['Sara', false],
|
|
||||||
['Piet', false],
|
|
||||||
['Lisa', true],
|
|
||||||
['Kees', false],
|
|
||||||
['Anna', false],
|
|
||||||
['Henk', false],
|
|
||||||
['Nina', false],
|
|
||||||
['Joost', false],
|
|
||||||
] as $i => [$name, $correct]) {
|
|
||||||
$answer = new Answer($name, $correct);
|
|
||||||
$answer->ordering = $i + 1;
|
|
||||||
$identiteit->addAnswer($answer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$quiz->addQuestion($identiteit);
|
return $this->toXlsx($spreadsheet);
|
||||||
}
|
|
||||||
|
|
||||||
return $this->quizToXlsx($quiz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @throws SpreadsheetDataException */
|
/** @throws SpreadsheetDataException */
|
||||||
@@ -96,16 +94,24 @@ class QuizSpreadsheetService
|
|||||||
$answerCounter = 1;
|
$answerCounter = 1;
|
||||||
$arrCounter = 1;
|
$arrCounter = 1;
|
||||||
|
|
||||||
while (\array_key_exists($arrCounter, $questionArr) && null !== $questionArr[$arrCounter]) {
|
while (true) {
|
||||||
|
try {
|
||||||
|
if (null === $questionArr[$arrCounter]) {
|
||||||
|
if (1 === $answerCounter) {
|
||||||
|
$errors[] = \sprintf('Question %d has no answers', $answerCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (\ErrorException) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
$answer = new Answer((string) $questionArr[$arrCounter++], (bool) $questionArr[$arrCounter++]);
|
$answer = new Answer((string) $questionArr[$arrCounter++], (bool) $questionArr[$arrCounter++]);
|
||||||
$answer->ordering = $answerCounter++;
|
$answer->ordering = $answerCounter++;
|
||||||
$question->addAnswer($answer);
|
$question->addAnswer($answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 === $answerCounter) {
|
|
||||||
$errors[] = \sprintf('Question %d has no answers', $question->ordering);
|
|
||||||
}
|
|
||||||
|
|
||||||
$quiz->addQuestion($question);
|
$quiz->addQuestion($question);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,41 +125,41 @@ class QuizSpreadsheetService
|
|||||||
$spreadsheet = new Spreadsheet();
|
$spreadsheet = new Spreadsheet();
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
$sheet = $spreadsheet->getActiveSheet();
|
||||||
|
|
||||||
// Write data rows first so we know the maximum answer count.
|
$sheet->getStyle('1:1')->getFont()->setBold(true);
|
||||||
$maxAnswers = 0;
|
|
||||||
|
$sheet->setCellValue('A1', 'Question');
|
||||||
|
$sheet->getColumnDimension('A')->setWidth(30);
|
||||||
|
$sheet->getStyle('A:A')->getAlignment()->setWrapText(true);
|
||||||
|
|
||||||
|
$counter = 1;
|
||||||
|
foreach (range('B', 'L', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Answer '.$counter++);
|
||||||
|
$sheet->getColumnDimension($column)->setWidth(30);
|
||||||
|
$sheet->getStyle($column.':'.$column)->getAlignment()->setWrapText(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (range('C', 'M', 2) as $column) {
|
||||||
|
$sheet->setCellValue($column.'1', 'Correct');
|
||||||
|
$sheet->getColumnDimension($column)->setAutoSize(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$answerColumns = range('B', 'L', 2);
|
||||||
|
$correctColumns = range('C', 'M', 2);
|
||||||
|
|
||||||
$row = 2;
|
$row = 2;
|
||||||
foreach ($quiz->questions as $question) {
|
foreach ($quiz->questions as $question) {
|
||||||
$sheet->setCellValue('A'.$row, $question->question);
|
$sheet->setCellValue('A'.$row, $question->question);
|
||||||
|
|
||||||
$col = 0;
|
$col = 0;
|
||||||
foreach ($question->answers as $answer) {
|
foreach ($question->answers as $answer) {
|
||||||
$sheet->setCellValue(Coordinate::stringFromColumnIndex(2 + 2 * $col).$row, $answer->text);
|
$sheet->setCellValue($answerColumns[$col].$row, $answer->text);
|
||||||
$sheet->setCellValue(Coordinate::stringFromColumnIndex(3 + 2 * $col).$row, $answer->isRightAnswer);
|
$sheet->setCellValue($correctColumns[$col].$row, $answer->isRightAnswer);
|
||||||
++$col;
|
++$col;
|
||||||
}
|
}
|
||||||
|
|
||||||
$maxAnswers = max($maxAnswers, $col);
|
|
||||||
++$row;
|
++$row;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write headers last, sized to the widest question.
|
|
||||||
$sheet->getStyle('1:1')->getFont()->setBold(true);
|
|
||||||
$sheet->setCellValue('A1', 'Question');
|
|
||||||
$sheet->getColumnDimension('A')->setWidth(30);
|
|
||||||
$sheet->getStyle('A:A')->getAlignment()->setWrapText(true);
|
|
||||||
|
|
||||||
for ($i = 0; $i < $maxAnswers; ++$i) {
|
|
||||||
$answerCol = Coordinate::stringFromColumnIndex(2 + 2 * $i);
|
|
||||||
$correctCol = Coordinate::stringFromColumnIndex(3 + 2 * $i);
|
|
||||||
|
|
||||||
$sheet->setCellValue($answerCol.'1', 'Answer '.($i + 1));
|
|
||||||
$sheet->getColumnDimension($answerCol)->setWidth(30);
|
|
||||||
$sheet->getStyle($answerCol.':'.$answerCol)->getAlignment()->setWrapText(true);
|
|
||||||
|
|
||||||
$sheet->setCellValue($correctCol.'1', 'Correct');
|
|
||||||
$sheet->getColumnDimension($correctCol)->setAutoSize(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->toXlsx($spreadsheet);
|
return $this->toXlsx($spreadsheet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
{% extends 'base.html.twig' %}
|
{% extends 'base.html.twig' %}
|
||||||
{% block importmap %}{{ importmap('quiz') }}{% endblock %}
|
{% block importmap %}{{ importmap('quiz') }}{% endblock %}
|
||||||
{% block nav %}{{ include('quiz/nav.html.twig') }}{% endblock %}
|
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
{% extends 'quiz/base.html.twig' %}
|
{% extends 'quiz/base.html.twig' %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="quiz-form-narrow">
|
|
||||||
{{ form(form) }}
|
{{ form(form) }}
|
||||||
</div>
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
{% if is_granted('IS_AUTHENTICATED') or app.current_route() == 'tvdt_quiz_select_season' %}
|
|
||||||
<div class="quiz-topbar">
|
|
||||||
{% if is_granted('IS_AUTHENTICATED') %}
|
|
||||||
<a href="{{ path('tvdt_backoffice_index') }}" class="btn btn-outline-secondary btn-sm">
|
|
||||||
{{ 'Backoffice'|trans }}
|
|
||||||
</a>
|
|
||||||
<a href="{{ path('tvdt_login_logout') }}" class="btn btn-outline-secondary btn-sm">
|
|
||||||
{{ 'Logout'|trans }}
|
|
||||||
</a>
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ path('tvdt_backoffice_index') }}" class="btn btn-outline-secondary btn-sm">
|
|
||||||
{{ 'Manage Quiz'|trans }}
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends 'quiz/base.html.twig' %}
|
{% extends 'quiz/base.html.twig' %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="quiz-content">
|
|
||||||
<h4>
|
<h4>
|
||||||
{% if season.settings.showNumbers %}
|
{% if season.settings.showNumbers %}
|
||||||
({{ question.ordering }}/{{ question.quiz.questions.count }})
|
({{ question.ordering }}/{{ question.quiz.questions.count }})
|
||||||
@@ -8,29 +7,24 @@
|
|||||||
</h4>
|
</h4>
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input type="hidden" name="token" value="{{ csrf_token('question') }}">
|
<input type="hidden" name="token" value="{{ csrf_token('question') }}">
|
||||||
{% set twoCol = question.answers|length >= 6 %}
|
|
||||||
{% if season.settings.confirmAnswers == false %}
|
{% if season.settings.confirmAnswers == false %}
|
||||||
<div class="{{ twoCol ? 'quiz-answers-grid' : '' }}">
|
|
||||||
{% for answer in question.answers %}
|
{% for answer in question.answers %}
|
||||||
<div class="py-2">
|
<div class="py-2">
|
||||||
<button class="answer-btn"
|
<button class="btn btn-outline-success"
|
||||||
type="submit"
|
type="submit"
|
||||||
name="answer"
|
name="answer"
|
||||||
value="{{ answer.id }}">{{ answer.text }}</button>
|
value="{{ answer.id }}">{{ answer.text }}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="{{ twoCol ? 'quiz-answers-grid' : '' }}">
|
|
||||||
{% for answer in question.answers %}
|
{% for answer in question.answers %}
|
||||||
<div class="py-1">
|
<div class="py-1">
|
||||||
<input required="required" type="radio" class="btn-check" name="answer"
|
<input required="required" type="radio" class="btn-check" name="answer"
|
||||||
id="answer-{{ loop.index0 }}" autocomplete="off"
|
id="answer-{{ loop.index0 }}" autocomplete="off"
|
||||||
value="{{ answer.id }}">
|
value="{{ answer.id }}">
|
||||||
<label class="answer-btn" for="answer-{{ loop.index0 }}">{{ answer.text }}</label>
|
<label class="btn btn-outline-secondary" for="answer-{{ loop.index0 }}">{{ answer.text }}</label>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
|
||||||
<div class="py-2">
|
<div class="py-2">
|
||||||
<button class="btn btn-success"
|
<button class="btn btn-success"
|
||||||
type="submit"
|
type="submit"
|
||||||
@@ -39,5 +33,4 @@
|
|||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{% extends 'quiz/base.html.twig' %}
|
{% extends 'quiz/base.html.twig' %}
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="quiz-form-narrow">
|
|
||||||
{{ form(form) }}
|
{{ form(form) }}
|
||||||
</div>
|
<a href="{{ path('tvdt_backoffice_index') }}" class="btn btn-outline-secondary">{{ 'Manage Quiz'|trans }}</a>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|||||||
@@ -4,11 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Tvdt\Tests\Service;
|
namespace Tvdt\Tests\Service;
|
||||||
|
|
||||||
use PhpOffice\PhpSpreadsheet\Reader;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Writer;
|
|
||||||
use PHPUnit\Framework\Attributes\CoversClass;
|
use PHPUnit\Framework\Attributes\CoversClass;
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Symfony\Component\HttpFoundation\File\File;
|
use Symfony\Component\HttpFoundation\File\File;
|
||||||
use Tvdt\Entity\Answer;
|
use Tvdt\Entity\Answer;
|
||||||
@@ -71,17 +67,12 @@ final class QuizSpreadsheetServiceTest extends TestCase
|
|||||||
$quiz = new Quiz();
|
$quiz = new Quiz();
|
||||||
$this->subject->xlsxToQuiz($quiz, new File($path));
|
$this->subject->xlsxToQuiz($quiz, new File($path));
|
||||||
|
|
||||||
$this->assertCount(2, $quiz->questions);
|
$this->assertCount(1, $quiz->questions);
|
||||||
|
|
||||||
/** @var Question $first */
|
/** @var Question $question */
|
||||||
$first = $quiz->questions->first();
|
$question = $quiz->questions->first();
|
||||||
$this->assertSame('Is de mol een man of een vrouw?', $first->question);
|
$this->assertSame('Is de mol een man of een vrouw?', $question->question);
|
||||||
$this->assertCount(2, $first->answers);
|
$this->assertCount(2, $question->answers);
|
||||||
|
|
||||||
/** @var Question $second */
|
|
||||||
$second = $quiz->questions->last();
|
|
||||||
$this->assertSame('Wie is de mol?', $second->question);
|
|
||||||
$this->assertCount(10, $second->answers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testQuizToXlsxEmptyQuizImportsWithNoQuestions(): void
|
public function testQuizToXlsxEmptyQuizImportsWithNoQuestions(): void
|
||||||
@@ -136,7 +127,6 @@ final class QuizSpreadsheetServiceTest extends TestCase
|
|||||||
$question = new Question();
|
$question = new Question();
|
||||||
$question->question = 'Unanswered question';
|
$question->question = 'Unanswered question';
|
||||||
$question->ordering = 1;
|
$question->ordering = 1;
|
||||||
|
|
||||||
$quiz->addQuestion($question);
|
$quiz->addQuestion($question);
|
||||||
|
|
||||||
$path = $this->captureXlsx($this->subject->quizToXlsx($quiz));
|
$path = $this->captureXlsx($this->subject->quizToXlsx($quiz));
|
||||||
@@ -144,97 +134,11 @@ final class QuizSpreadsheetServiceTest extends TestCase
|
|||||||
try {
|
try {
|
||||||
$this->subject->xlsxToQuiz(new Quiz(), new File($path));
|
$this->subject->xlsxToQuiz(new Quiz(), new File($path));
|
||||||
$this->fail('Expected SpreadsheetDataException to be thrown');
|
$this->fail('Expected SpreadsheetDataException to be thrown');
|
||||||
} catch (SpreadsheetDataException $spreadsheetDataException) {
|
} catch (SpreadsheetDataException $e) {
|
||||||
$this->assertNotEmpty($spreadsheetDataException->errors);
|
$this->assertNotEmpty($e->errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testXlsxToQuizStopsAtBlankRow(): void
|
|
||||||
{
|
|
||||||
$spreadsheet = new Spreadsheet();
|
|
||||||
$sheet = $spreadsheet->getActiveSheet();
|
|
||||||
$sheet->setCellValue('A1', 'Question');
|
|
||||||
$sheet->setCellValue('B1', 'Answer 1');
|
|
||||||
$sheet->setCellValue('C1', 'Correct');
|
|
||||||
$sheet->setCellValue('A2', 'First question');
|
|
||||||
$sheet->setCellValue('B2', 'Yes');
|
|
||||||
$sheet->setCellValue('C2', true);
|
|
||||||
// Row 3 intentionally blank — should halt parsing
|
|
||||||
$sheet->setCellValue('A4', 'Second question');
|
|
||||||
$sheet->setCellValue('B4', 'No');
|
|
||||||
$sheet->setCellValue('C4', false);
|
|
||||||
|
|
||||||
$path = $this->createTempPath('.xlsx');
|
|
||||||
ob_start();
|
|
||||||
new Writer\Xlsx($spreadsheet)->save('php://output');
|
|
||||||
file_put_contents($path, ob_get_clean());
|
|
||||||
|
|
||||||
$quiz = new Quiz();
|
|
||||||
$this->subject->xlsxToQuiz($quiz, new File($path));
|
|
||||||
|
|
||||||
$this->assertCount(1, $quiz->questions);
|
|
||||||
/** @var Question $first */
|
|
||||||
$first = $quiz->questions->first();
|
|
||||||
$this->assertSame('First question', $first->question);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return \Iterator<string, array{int, string, int, string, int, int}> */
|
|
||||||
public static function answerCountHeaderProvider(): \Iterator
|
|
||||||
{
|
|
||||||
// Columns (0-based): Question=0, Answer1=1, Correct=2, Answer2=3, Correct=4, …
|
|
||||||
// Answer N is at index 1+2*(N-1) = 2N-1, Correct N at 2+2*(N-1) = 2N.
|
|
||||||
yield '2 answers → 2 header pairs' => [2, 'Answer 2', 3, 'Correct', 4, 5];
|
|
||||||
yield '6 answers → 6 header pairs' => [6, 'Answer 6', 11, 'Correct', 12, 13];
|
|
||||||
yield '7 answers → 7 header pairs' => [7, 'Answer 7', 13, 'Correct', 14, 15];
|
|
||||||
yield '10 answers → 10 header pairs' => [10, 'Answer 10', 19, 'Correct', 20, 21];
|
|
||||||
}
|
|
||||||
|
|
||||||
#[DataProvider('answerCountHeaderProvider')]
|
|
||||||
public function testQuizToXlsxHeaderCountMatchesAnswerCount(
|
|
||||||
int $answerCount,
|
|
||||||
string $lastAnswerHeader,
|
|
||||||
int $lastAnswerIndex,
|
|
||||||
string $lastCorrectHeader,
|
|
||||||
int $lastCorrectIndex,
|
|
||||||
int $absentIndex,
|
|
||||||
): void {
|
|
||||||
$path = $this->captureXlsx($this->subject->quizToXlsx($this->makeQuizWithAnswerCounts($answerCount)));
|
|
||||||
$headers = $this->readFirstRow($path);
|
|
||||||
|
|
||||||
$this->assertSame($lastAnswerHeader, $headers[$lastAnswerIndex]);
|
|
||||||
$this->assertSame($lastCorrectHeader, $headers[$lastCorrectIndex]);
|
|
||||||
$this->assertArrayNotHasKey($absentIndex, $headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testQuizToXlsxHeadersMatchMaxAnswersAcrossQuestions(): void
|
|
||||||
{
|
|
||||||
$quiz = new Quiz();
|
|
||||||
$quiz->addQuestion($this->makeQuestion('Short', 3));
|
|
||||||
$quiz->addQuestion($this->makeQuestion('Long', 7));
|
|
||||||
$quiz->addQuestion($this->makeQuestion('Medium', 5));
|
|
||||||
|
|
||||||
$path = $this->captureXlsx($this->subject->quizToXlsx($quiz));
|
|
||||||
$headers = $this->readFirstRow($path);
|
|
||||||
|
|
||||||
$this->assertSame('Answer 7', $headers[13]);
|
|
||||||
$this->assertSame('Correct', $headers[14]);
|
|
||||||
$this->assertArrayNotHasKey(15, $headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testQuizToXlsxRoundTripWithSevenAnswers(): void
|
|
||||||
{
|
|
||||||
$original = $this->makeQuizWithAnswerCounts(7);
|
|
||||||
$path = $this->captureXlsx($this->subject->quizToXlsx($original));
|
|
||||||
|
|
||||||
$imported = new Quiz();
|
|
||||||
$this->subject->xlsxToQuiz($imported, new File($path));
|
|
||||||
|
|
||||||
$this->assertCount(1, $imported->questions);
|
|
||||||
/** @var Question $question */
|
|
||||||
$question = $imported->questions->first();
|
|
||||||
$this->assertCount(7, $question->answers);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function makeQuiz(): Quiz
|
private function makeQuiz(): Quiz
|
||||||
{
|
{
|
||||||
$quiz = new Quiz();
|
$quiz = new Quiz();
|
||||||
@@ -258,36 +162,6 @@ final class QuizSpreadsheetServiceTest extends TestCase
|
|||||||
return $quiz;
|
return $quiz;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function makeQuizWithAnswerCounts(int ...$counts): Quiz
|
|
||||||
{
|
|
||||||
$quiz = new Quiz();
|
|
||||||
foreach ($counts as $i => $count) {
|
|
||||||
$quiz->addQuestion($this->makeQuestion('Question '.$i, $count));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $quiz;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function makeQuestion(string $text, int $answerCount): Question
|
|
||||||
{
|
|
||||||
$question = new Question();
|
|
||||||
$question->question = $text;
|
|
||||||
$question->ordering = 1;
|
|
||||||
for ($i = 1; $i <= $answerCount; ++$i) {
|
|
||||||
$question->addAnswer(new Answer('Answer '.$i, isRightAnswer: false));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $question;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return array<int, string|null> */
|
|
||||||
private function readFirstRow(string $path): array
|
|
||||||
{
|
|
||||||
$rows = new Reader\Xlsx()->setReadDataOnly(true)->load($path)->getActiveSheet()->toArray(formatData: false);
|
|
||||||
|
|
||||||
return $rows[0] ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
private function captureXlsx(\Closure $closure): string
|
private function captureXlsx(\Closure $closure): string
|
||||||
{
|
{
|
||||||
$path = $this->createTempPath('.xlsx');
|
$path = $this->createTempPath('.xlsx');
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Tvdt\Tests\Twig;
|
|
||||||
|
|
||||||
use PHPUnit\Framework\Assert;
|
|
||||||
use PHPUnit\Framework\Attributes\DataProvider;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
|
||||||
|
|
||||||
use function Safe\file_get_contents;
|
|
||||||
use function Safe\preg_match_all;
|
|
||||||
|
|
||||||
final class TemplateReferencesTest extends TestCase
|
|
||||||
{
|
|
||||||
private static string $templatesDir;
|
|
||||||
|
|
||||||
public static function setUpBeforeClass(): void
|
|
||||||
{
|
|
||||||
self::$templatesDir = \dirname(__DIR__, 2).'/templates';
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return iterable<string, array{string, string}> */
|
|
||||||
public static function templateReferenceProvider(): iterable
|
|
||||||
{
|
|
||||||
$templatesDir = \dirname(__DIR__, 2).'/templates';
|
|
||||||
$iterator = new \RecursiveIteratorIterator(
|
|
||||||
new \RecursiveDirectoryIterator($templatesDir, \RecursiveDirectoryIterator::SKIP_DOTS),
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($iterator as $file) {
|
|
||||||
Assert::assertInstanceOf(\SplFileInfo::class, $file);
|
|
||||||
if ('twig' !== $file->getExtension()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = file_get_contents($file->getPathname());
|
|
||||||
$sourceFile = str_replace($templatesDir.'/', '', $file->getPathname());
|
|
||||||
|
|
||||||
// Match extends, include(), and embed tags — capture the quoted template name
|
|
||||||
preg_match_all(
|
|
||||||
'/(?:extends|include|embed)\s*\(?[\'"]([^\'"]+)[\'"]\)?/',
|
|
||||||
$content,
|
|
||||||
$matches,
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($matches[1] as $referencedTemplate) {
|
|
||||||
yield \sprintf('%s → %s', $sourceFile, $referencedTemplate) => [$sourceFile, $referencedTemplate];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[DataProvider('templateReferenceProvider')]
|
|
||||||
public function testReferencedTemplateExists(string $sourceFile, string $referencedTemplate): void
|
|
||||||
{
|
|
||||||
$absolutePath = self::$templatesDir.'/'.$referencedTemplate;
|
|
||||||
|
|
||||||
$this->assertFileExists(
|
|
||||||
$absolutePath,
|
|
||||||
\sprintf("Template '%s' references '%s' which does not exist at '%s'.", $sourceFile, $referencedTemplate, $absolutePath),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user