From 0fc894f3bc06a798cf8ec16a7b0676fadd7e2628 Mon Sep 17 00:00:00 2001 From: "lina.wolf" Date: Sun, 12 May 2024 21:01:15 +0200 Subject: [PATCH] [TASK] Streamline `Build/Scripts/runTests.sh` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Following the scheme provided by @sbuerk This change modifies the `Build/Scripts/runTests.sh` execution wrapper to be in line with current TYPO3 core implementation. This contains following tasks: * Modify `Build/Scripts/runTests.sh`:     * `-b ` switch to determine which       container binary should be used.     * Remove the usage of `docker-compose.yml` file and       usage by replacing container execution call with       docker or podman binary calls.     * Include `bash trap` logic for container/network       cleanup on abort signals.     * Keep core `xdebug` flag ability, albeit not used       currently due to not having tests included. * Refactor suit command execution without docker-compose. * Remove `Build/testing-docker/docker-compose.yml` due   to being obsolete now. * Add composer related temporary files to `.gitignore`   and `.gitattributes`. * Add documentation rendering and test rendering to the   `runTests.sh`. * `-s composerUpdate` requires different temporary dependencies based on the selected TYPO3 core version (`-t`), without leaving root composer.json in a changed state. * In addition to the replaced `docker-compose.yml` file, 11.4 core install is removed and 13.1 added. * TYPO3 v13.1 testing is added as GitHub action workflow. * `typo3/coding-standards` is required in dev-main to support symfony 7.x until a version is released. * `--no-check-lock` added for `-s composerValidate` to avoid irritating error-message due to temporary dependency require. As `composer.lock` is not committed, it does not make much sense anyway. * `--no-check-lock` and `--no-update-lock` added to `-s composerNormalize` to avoid irritating error-message due to temporary dependency require. As `composer.lock` is not committed, it does not make much sense anyway. Additionall, license is modified in `composer.json` to mitigate composer validation error: License "GPL-2.0+" is a deprecated SPDX license identifier, use "GPL-2.0-or-later" instead Used command(s): ```terminal composer require --dev --no-update \ "typo3/testing-framework":"^8.0.9" \ "typo3/coding-standards":"dev-main" composer require --no-update \ "typo3/cms-core":"^12.4 || ^13.0 || ^13.1 || dev-main" ``` --- .github/workflows/cgl.yml | 4 + .github/workflows/tests-13.1.yml | 26 ++ Build/Scripts/runTests.sh | 435 +++++++++++------- Build/phpstan/phpstan-baseline.neon | 46 ++ Build/phpstan/phpstan-typo3-constants.php | 18 + Build/phpstan/phpstan.neon | 22 + Build/rector/rector.php | 58 +++ Build/testing-docker/docker-compose.yml | 147 ------ .../Exceptions/ClassNotPublicException.php | 4 +- .../InvalidConfigurationException.php | 4 +- Classes/Util/ArrayHelper.php | 2 +- Classes/Util/ClassDocsHelper.php | 25 +- Classes/Util/ClassHelper.php | 16 +- Classes/Util/CodeSnippetCreator.php | 4 +- Classes/Util/FileHelper.php | 6 +- Classes/Util/JsonHelper.php | 2 +- Classes/Util/Typo3CodeSnippets.php | 2 +- .../Unit/Service/TestClasses/MyFirstClass.php | 4 +- .../Service/TestClasses/MySecondClass.php | 4 +- composer.json | 15 +- 20 files changed, 490 insertions(+), 354 deletions(-) create mode 100644 .github/workflows/tests-13.1.yml create mode 100644 Build/phpstan/phpstan-baseline.neon create mode 100644 Build/phpstan/phpstan-typo3-constants.php create mode 100644 Build/phpstan/phpstan.neon create mode 100644 Build/rector/rector.php delete mode 100644 Build/testing-docker/docker-compose.yml diff --git a/.github/workflows/cgl.yml b/.github/workflows/cgl.yml index 41a202c..9335f6c 100644 --- a/.github/workflows/cgl.yml +++ b/.github/workflows/cgl.yml @@ -42,6 +42,10 @@ jobs: core: '13.0' - php: '8.3' core: '13.0' + - php: '8.2' + core: '13.1' + - php: '8.3' + core: '13.1' - php: '8.2' core: 'main' - php: '8.3' diff --git a/.github/workflows/tests-13.1.yml b/.github/workflows/tests-13.1.yml new file mode 100644 index 0000000..ff1fdbe --- /dev/null +++ b/.github/workflows/tests-13.1.yml @@ -0,0 +1,26 @@ +name: tests 13.1 + +on: + push: + pull_request: + schedule: + - cron: '56 4 * * *' + +jobs: + unit: + name: Unit Tests + runs-on: ubuntu-latest + strategy: + matrix: + php: + - '8.2' + - '8.3' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install testing system + run: Build/Scripts/runTests.sh -t 13.1 -p ${{ matrix.php }} -s composerUpdate + + - name: Unit Tests + run: Build/Scripts/runTests.sh -t 13.1 -p ${{ matrix.php }} -s unit diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh index 85914b6..0718a10 100755 --- a/Build/Scripts/runTests.sh +++ b/Build/Scripts/runTests.sh @@ -1,101 +1,86 @@ #!/usr/bin/env bash # -# TYPO3 core test runner based on docker and docker-compose. +# EXT:examples test runner based on docker/podman. # -# Function to write a .env file in Build/testing-docker -# This is read by docker-compose and vars defined here are -# used in Build/testing-docker/docker-compose.yml -setUpDockerComposeDotEnv() { - # Delete possibly existing local .env file if exists - [ -e .env ] && rm .env - # Set up a new .env file for docker-compose - { - echo "COMPOSE_PROJECT_NAME=local" - # To prevent access rights of files created by the testing, the docker image later - # runs with the same user that is currently executing the script. docker-compose can't - # use $UID directly itself since it is a shell variable and not an env variable, so - # we have to set it explicitly here. - echo "HOST_UID=`id -u`" - # Your local user - echo "ROOT_DIR=${ROOT_DIR}" - echo "HOST_USER=${USER}" - echo "TEST_FILE=${TEST_FILE}" - echo "TYPO3_VERSION=${TYPO3_VERSION}" - echo "PHP_XDEBUG_ON=${PHP_XDEBUG_ON}" - echo "PHP_XDEBUG_PORT=${PHP_XDEBUG_PORT}" - echo "DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE}" - echo "EXTRA_TEST_OPTIONS=${EXTRA_TEST_OPTIONS}" - echo "SCRIPT_VERBOSE=${SCRIPT_VERBOSE}" - echo "CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN}" - echo "COMPOSER_NORMALIZE_DRY_RUN=${COMPOSER_NORMALIZE_DRY_RUN}" - } > .env +cleanUp() { + ATTACHED_CONTAINERS=$(${CONTAINER_BIN} ps --filter network=${NETWORK} --format='{{.Names}}') + for ATTACHED_CONTAINER in ${ATTACHED_CONTAINERS}; do + ${CONTAINER_BIN} rm -f ${ATTACHED_CONTAINER} >/dev/null + done + ${CONTAINER_BIN} network rm ${NETWORK} >/dev/null } -# Load help text into $HELP -read -r -d '' HELP <=20.10 for xdebug break pointing to work reliably, and -a recent docker-compose (tested >=1.21.2) is needed. +cleanRenderedDocumentationFiles() { + echo -n "Clean rendered documentation files ... " + rm -rf \ + Documentation-GENERATED-temp + echo "done" +} -Usage: $0 [options] [file] +loadHelp() { + # Load help text into $HELP + read -r -d '' HELP < Specifies which test suite to run - cgl: cgl test and fix all php files - - clean: Cleanup non-repo files from testing + - clean: Clean temporary files + - cleanCache: Clean cache folds for files. + - cleanRenderedDocumentation: Clean existing rendered documentation output. + - composer: "composer" with all remaining arguments dispatched. - composerNormalize: "composer normalize" - composerUpdate: "composer update", handy if host has no PHP - composerValidate: "composer validate" - lint: PHP linting - - unit (default): PHP unit tests + - phpstan: PHPStan static analysis + - phpstanBaseline: Generate PHPStan baseline + - rector: Apply Rector rules + - renderDocumentation + - testRenderDocumentation + - unit + + -b + Container environment: + - docker + - podman + + If not specified, podman will be used if available. Otherwise, docker is used. - -p <8.1|8.2> + -p <8.1|8.2|8.3> Specifies the PHP minor version to be used - - 8.1 (default): use PHP 8.1 + - 8.1: (default) use PHP 8.1 - 8.2: use PHP 8.2 + - 8.3: use PHP 8.3 - -e "" - Only with -s unit - Additional options to send to phpunit (unit tests). - Options starting with "--" must be added after options starting with "-". - Example -e "-v --filter canRetrieveValueWithGP" to enable verbose output AND filter tests - named "canRetrieveValueWithGP" - - -t <12.4|13.0|main> + -t <12.4|13.0|13.1|main> Only with -s composerUpdate Specifies the TYPO3 core major version to be used - 12.4 (default): use TYPO3 core v12 - 13.0: use TYPO3 core v13.0 + - 13.1: use TYPO3 core v13.1 - main: use TYPO3 core main - - -x - Only with -s unit|acceptance - Send information to host instance for test or system under test break points. This is especially - useful if a local PhpStorm instance is listening on default xdebug port 9003. A different port - can be selected with -y - - -y - Send xdebug information to a different port than default 9003 if an IDE like PhpStorm - is not listening on default port. - -n - Only with -s cgl, composerNormalize + Only with -s cgl, composerNormalize, rector Activate dry-run in CGL check and composer normalize that does not actively change files and only prints broken ones. -u - Update existing typo3/core-testing-*:latest docker images. Maintenance call to docker pull latest - versions of the main php images. The images are updated once in a while and only the youngest - ones are supported by core testing. Use this if weird test errors occur. Also removes obsolete - image versions of typo3/core-testing-*. - - -v - Enable verbose script output. Shows variables and docker commands. + Update existing typo3/core-testing-*:latest container images and remove dangling local volumes. + New images are published once in a while and only the latest ones are supported by core testing. + Use this if weird test errors occur. Also removes obsolete image versions of typo3/core-testing-*. -h Show this help. @@ -104,65 +89,42 @@ Examples: # Run unit tests using PHP 8.1 ./Build/Scripts/runTests.sh EOF +} -# Test if docker-compose exists, else exit out with error -if ! type "docker-compose" > /dev/null; then - echo "This script relies on docker and docker-compose. Please install" >&2 - exit 1 +# Test if docker exists, else exit out with error +if ! type "docker" >/dev/null 2>&1 && ! type "podman" >/dev/null 2>&1; then + echo "This script relies on docker or podman. Please install" >&2 + exit 1 fi -# Go to the directory this script is located, so everything else is relative -# to this dir, no matter from where this script is called. -THIS_SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -cd "$THIS_SCRIPT_DIR" || exit 1 - -# Go to directory that contains the local docker-compose.yml file -cd ../testing-docker || exit 1 - # Option defaults -if ! command -v realpath &> /dev/null; then - echo "This script works best with realpath installed" >&2 - ROOT_DIR="${PWD}/../../" -else - ROOT_DIR=`realpath ${PWD}/../../` -fi TEST_SUITE="cgl" PHP_VERSION="8.1" -TYPO3_VERSION="11.5" PHP_XDEBUG_ON=0 PHP_XDEBUG_PORT=9003 -SCRIPT_VERBOSE=0 -CGLCHECK_DRY_RUN="" -COMPOSER_NORMALIZE_DRY_RUN="" +CGLCHECK_DRY_RUN=0 +CI_PARAMS="${CI_PARAMS:-}" +DOCS_PARAMS="${DOCS_PARAMS:=--pull always}" +CONTAINER_BIN="" +CONTAINER_HOST="host.docker.internal" +TYPO3_VERSION="12.4" -# Option parsing +# Option parsing updates above default vars # Reset in case getopts has been used previously in the shell OPTIND=1 # Array for invalid options -INVALID_OPTIONS=(); -# Simple option parsing based on getopts (! not getopt). GNU getopts is available on linux and mac systems, -# where GNU getop may be not installed on mac systems. -while getopts ":s:p:t:e:xynhuv" OPT; do +INVALID_OPTIONS=() +# Simple option parsing based on getopts (! not getopt) +while getopts "b:s:p:t:xy:nhu" OPT; do case ${OPT} in - e) - EXTRA_TEST_OPTIONS=${OPTARG} - ;; - h) - echo "${HELP}" - exit 0 - ;; s) TEST_SUITE=${OPTARG} ;; - t) - TYPO3_VERSION=${OPTARG} - if ! [[ ${TYPO3_VERSION} =~ ^(12.4|13.0|main)$ ]]; then - INVALID_OPTIONS+=("t ${OPTARG}") + b) + if ! [[ ${OPTARG} =~ ^(docker|podman)$ ]]; then + INVALID_OPTIONS+=("${OPTARG}") fi - ;; - n) - CGLCHECK_DRY_RUN="-n" - COMPOSER_NORMALIZE_DRY_RUN="--dry-run" + CONTAINER_BIN=${OPTARG} ;; p) PHP_VERSION=${OPTARG} @@ -170,11 +132,11 @@ while getopts ":s:p:t:e:xynhuv" OPT; do INVALID_OPTIONS+=("p ${OPTARG}") fi ;; - u) - TEST_SUITE=update - ;; - v) - SCRIPT_VERBOSE=1 + t) + TYPO3_VERSION=${OPTARG} + if ! [[ ${TYPO3_VERSION} =~ ^(12.4|13.0|13.1|main)$ ]]; then + INVALID_OPTIONS+=("t ${OPTARG}") + fi ;; x) PHP_XDEBUG_ON=1 @@ -182,11 +144,22 @@ while getopts ":s:p:t:e:xynhuv" OPT; do y) PHP_XDEBUG_PORT=${OPTARG} ;; + n) + CGLCHECK_DRY_RUN=1 + ;; + h) + loadHelp + echo "${HELP}" + exit 0 + ;; + u) + TEST_SUITE=update + ;; \?) - INVALID_OPTIONS+=(${OPTARG}) + INVALID_OPTIONS+=("${OPTARG}") ;; :) - INVALID_OPTIONS+=(${OPTARG}) + INVALID_OPTIONS+=("${OPTARG}") ;; esac done @@ -198,91 +171,235 @@ if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then echo "-"${I} >&2 done echo >&2 - echo "${HELP}" >&2 + echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options" exit 1 fi -# Move "8.1" to "php81", the latter is the docker container name -DOCKER_PHP_IMAGE=`echo "php${PHP_VERSION}" | sed -e 's/\.//'` +COMPOSER_ROOT_VERSION="13.0.x-dev" +HOST_UID=$(id -u) +USERSET="" +if [ $(uname) != "Darwin" ]; then + USERSET="--user $HOST_UID" +fi + +# Go to the directory this script is located, so everything else is relative +# to this dir, no matter from where this script is called, then go up two dirs. +THIS_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" +cd "$THIS_SCRIPT_DIR" || exit 1 +cd ../../ || exit 1 +ROOT_DIR="${PWD}" + +# Create .cache dir: composer need this. +mkdir -p .Build/.cache +mkdir -p .Build/Web/typo3temp/var/tests + +IMAGE_PREFIX="docker.io/" +# Non-CI fetches TYPO3 images (php and nodejs) from ghcr.io +TYPO3_IMAGE_PREFIX="ghcr.io/typo3/" +CONTAINER_INTERACTIVE="-it --init" + +IS_CORE_CI=0 +# ENV var "CI" is set by gitlab-ci. We use it here to distinct 'local' and 'CI' environment. +if [ "${CI}" == "true" ]; then + IS_CORE_CI=1 + IMAGE_PREFIX="" + CONTAINER_INTERACTIVE="" +fi + +# determine default container binary to use: 1. podman 2. docker +if [[ -z "${CONTAINER_BIN}" ]]; then + if type "podman" >/dev/null 2>&1; then + CONTAINER_BIN="podman" + elif type "docker" >/dev/null 2>&1; then + CONTAINER_BIN="docker" + fi +fi + +IMAGE_PHP="${TYPO3_IMAGE_PREFIX}core-testing-$(echo "php${PHP_VERSION}" | sed -e 's/\.//'):latest" +IMAGE_ALPINE="${IMAGE_PREFIX}alpine:3.8" +IMAGE_DOCS="ghcr.io/typo3-documentation/render-guides:latest" # Set $1 to first mass argument, this is the optional test file or test directory to execute shift $((OPTIND - 1)) -TEST_FILE=${1} -if [ -n "${1}" ]; then - TEST_FILE="Web/typo3conf/ext/codesnippet/${1}" + +SUFFIX=$(echo $RANDOM) +NETWORK="t3docsexamples-${SUFFIX}" +${CONTAINER_BIN} network create ${NETWORK} >/dev/null + +if [ ${CONTAINER_BIN} = "docker" ]; then + # docker needs the add-host for xdebug remote debugging. podman has host.container.internal built in + CONTAINER_COMMON_PARAMS="${CONTAINER_INTERACTIVE} --rm --network ${NETWORK} --add-host "${CONTAINER_HOST}:host-gateway" ${USERSET} -v ${ROOT_DIR}:${ROOT_DIR} -w ${ROOT_DIR}" + CONTAINER_DOCS_PARAMS="${CONTAINER_INTERACTIVE} ${DOCS_PARAMS} --rm --network ${NETWORK} --add-host "${CONTAINER_HOST}:host-gateway" ${USERSET} -v ${ROOT_DIR}:/project" +else + # podman + CONTAINER_HOST="host.containers.internal" + CONTAINER_COMMON_PARAMS="${CONTAINER_INTERACTIVE} ${CI_PARAMS} --rm --network ${NETWORK} -v ${ROOT_DIR}:${ROOT_DIR} -w ${ROOT_DIR}" + CONTAINER_DOCS_PARAMS="${CONTAINER_INTERACTIVE} ${DOCS_PARAMS} --rm --network ${NETWORK} -v ${ROOT_DIR}:/project" fi -if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x +if [ ${PHP_XDEBUG_ON} -eq 0 ]; then + XDEBUG_MODE="-e XDEBUG_MODE=off" + XDEBUG_CONFIG=" " +else + XDEBUG_MODE="-e XDEBUG_MODE=debug -e XDEBUG_TRIGGER=foo" + XDEBUG_CONFIG="client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal" fi # Suite execution case ${TEST_SUITE} in cgl) - # Active dry-run for cgl needs not "-n" but specific options - if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then - CGLCHECK_DRY_RUN="--dry-run --diff" + if [ "${CGLCHECK_DRY_RUN}" -eq 1 ]; then + COMMAND="php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v --dry-run --diff --config=Build/php-cs-fixer/.php-cs-fixer.dist.php --using-cache=no ." + else + COMMAND="php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v --config=Build/php-cs-fixer/.php-cs-fixer.dist.php --using-cache=no ." fi - setUpDockerComposeDotEnv - docker-compose run cgl + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name cgl-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}" SUITE_EXIT_CODE=$? - docker-compose down ;; clean) - rm -rf \ - ../../composer.lock \ - ../../.Build/ \ - ../../.cache/ \ - ../../composer.json.testing \ - ../../var/ + cleanCacheFiles + cleanRenderedDocumentationFiles + ;; + cleanCache) + cleanCacheFiles + ;; + cleanRenderedDocumentation) + cleanRenderedDocumentationFiles + ;; + composer) + COMMAND=(composer "$@") + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-command-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + SUITE_EXIT_CODE=$? ;; composerNormalize) - setUpDockerComposeDotEnv - docker-compose run composer_normalize + if [ "${CGLCHECK_DRY_RUN}" -eq 1 ]; then + COMMAND=(composer normalize --no-check-lock --no-update-lock -n) + else + COMMAND=(composer normalize --no-check-lock --no-update-lock) + fi + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-command-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" SUITE_EXIT_CODE=$? - docker-compose down ;; composerUpdate) - setUpDockerComposeDotEnv - cp ../../composer.json ../../composer.json.orig - if [ -f "../../composer.json.testing" ]; then - cp ../../composer.json ../../composer.json.orig + rm -rf .Build/bin/ .Build/typo3 .Build/vendor .Build/Web ./composer.lock + cp ${ROOT_DIR}/composer.json ${ROOT_DIR}/composer.json.orig + if [ -f "${ROOT_DIR}/composer.json.testing" ]; then + cp ${ROOT_DIR}/composer.json ${ROOT_DIR}/composer.json.orig + fi + if [ "${TYPO3_VERSION}" == "12.4" ]; then + COMMAND=(composer req typo3/cms-core:~12.4@dev -W --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" fi - docker-compose run composer_update - cp ../../composer.json ../../composer.json.testing - mv ../../composer.json.orig ../../composer.json + if [ "${TYPO3_VERSION}" == "13.0" ]; then + COMMAND=(composer req --dev --no-update typo3/cms-backend:~13.0.1@dev typo3/cms-recordlist:~13.0.1@dev typo3/cms-frontend:~13.0.1@dev typo3/cms-extbase:~13.0.1@dev typo3/cms-fluid:~13.0.1@dev typo3/cms-install:~13.0.1@dev --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-dev-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + COMMAND=(composer req typo3/cms-core:~13.0.1@dev -W --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + fi + if [ "${TYPO3_VERSION}" == "13.1" ]; then + COMMAND=(composer req --dev --no-update typo3/cms-backend:~13.1@dev typo3/cms-recordlist:~13.1@dev typo3/cms-frontend:~13.1@dev typo3/cms-extbase:~13.1@dev typo3/cms-fluid:~13.1@dev typo3/cms-install:~13.1@dev --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-dev-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + COMMAND=(composer req typo3/cms-core:~13.1@dev -W --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + fi + if [ "${TYPO3_VERSION}" == "main" ]; then + COMMAND=(composer req --dev --no-update typo3/cms-backend:dev-main typo3/cms-recordlist:dev-main typo3/cms-frontend:dev-main typo3/cms-extbase:dev-main typo3/cms-fluid:dev-main typo3/cms-install:dev-main --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-dev-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + COMMAND=(composer req typo3/cms-core:dev-main -W --no-update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-prepare-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + fi + COMMAND=(composer update --no-ansi --no-interaction --no-progress) + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-install-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" SUITE_EXIT_CODE=$? - docker-compose down + cp ${ROOT_DIR}/composer.json ${ROOT_DIR}/composer.json.testing + mv ${ROOT_DIR}/composer.json.orig ${ROOT_DIR}/composer.json ;; composerValidate) - setUpDockerComposeDotEnv - docker-compose run composer_validate + COMMAND=(composer validate --no-check-lock "$@") + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-command-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" SUITE_EXIT_CODE=$? - docker-compose down ;; lint) - setUpDockerComposeDotEnv - docker-compose run lint + COMMAND="find . -name \\*.php ! -path "./.Build/\\*" -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null" + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-command-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}" SUITE_EXIT_CODE=$? - docker-compose down ;; - unit) - setUpDockerComposeDotEnv - docker-compose run unit + phpstan) + COMMAND="php -dxdebug.mode=off .Build/bin/phpstan --configuration=Build/phpstan/phpstan.neon" + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}" + SUITE_EXIT_CODE=$? + ;; + phpstanBaseline) + COMMAND="php -dxdebug.mode=off .Build/bin/phpstan --configuration=Build/phpstan/phpstan.neon --generate-baseline=Build/phpstan/phpstan-baseline.neon -v" + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}" + SUITE_EXIT_CODE=$? + ;; + rector) + if [ "${CGLCHECK_DRY_RUN}" -eq 1 ]; then + COMMAND=(php -dxdebug.mode=off .Build/bin/rector -n --config=Build/rector/rector.php --clear-cache "$@") + else + COMMAND=(php -dxdebug.mode=off .Build/bin/rector --config=Build/rector/rector.php --clear-cache "$@") + fi + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name rector-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} "${COMMAND[@]}" + SUITE_EXIT_CODE=$? + ;; + renderDocumentation) + COMMAND=(--config=Documentation "$@") + mkdir -p Documentation-GENERATED-temp + ${CONTAINER_BIN} run ${CONTAINER_INTERACTIVE} ${CONTAINER_DOCS_PARAMS} --name render-documentation-${SUFFIX} ${IMAGE_DOCS} "${COMMAND[@]}" + SUITE_EXIT_CODE=$? + ;; + testRenderDocumentation) + COMMAND=(--config=Documentation --no-progress --fail-on-log "$@") + mkdir -p Documentation-GENERATED-temp + ${CONTAINER_BIN} run ${CONTAINER_INTERACTIVE} ${CONTAINER_DOCS_PARAMS} --name render-documentation-test-${SUFFIX} ${IMAGE_DOCS} "${COMMAND[@]}" SUITE_EXIT_CODE=$? - docker-compose down ;; update) - # pull typo3/core-testing-*:latest versions of those ones that exist locally - docker images typo3/core-testing-*:latest --format "{{.Repository}}:latest" | xargs -I {} docker pull {} + # pull typo3/core-testing-* versions of those ones that exist locally + echo "> pull ${TYPO3_IMAGE_PREFIX}core-testing-* versions of those ones that exist locally" + ${CONTAINER_BIN} images "${TYPO3_IMAGE_PREFIX}core-testing-*" --format "{{.Repository}}:{{.Tag}}" | xargs -I {} ${CONTAINER_BIN} pull {} + echo "" # remove "dangling" typo3/core-testing-* images (those tagged as ) - docker images typo3/core-testing-* --filter "dangling=true" --format "{{.ID}}" | xargs -I {} docker rmi {} + echo "> remove \"dangling\" ${TYPO3_IMAGE_PREFIX}/core-testing-* images (those tagged as )" + ${CONTAINER_BIN} images --filter "reference=${TYPO3_IMAGE_PREFIX}/core-testing-*" --filter "dangling=true" --format "{{.ID}}" | xargs -I {} ${CONTAINER_BIN} rmi -f {} + echo "" + ;; + unit) + COMMAND="php -dxdebug.mode=off .Build/bin/phpunit -c Build/php-unit/UnitTests.xml" + ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer -e COMPOSER_ROOT_VERSION=${COMPOSER_ROOT_VERSION} ${IMAGE_PHP} /bin/sh -c "${COMMAND}" + SUITE_EXIT_CODE=$? ;; *) + loadHelp echo "Invalid -s option argument ${TEST_SUITE}" >&2 echo >&2 echo "${HELP}" >&2 exit 1 + ;; esac +cleanUp + +# Print summary +echo "" >&2 +echo "###########################################################################" >&2 +echo "Result of ${TEST_SUITE}" >&2 +echo "Container runtime: ${CONTAINER_BIN}" >&2 +if [[ ${IS_CORE_CI} -eq 1 ]]; then + echo "Environment: CI" >&2 +else + echo "Environment: local" >&2 +fi +echo "PHP: ${PHP_VERSION}" >&2 +echo "TYPO3: ${CORE_VERSION}" >&2 +if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then + echo "SUCCESS" >&2 +else + echo "FAILURE" >&2 +fi +echo "###########################################################################" >&2 +echo "" >&2 + +# Exit with code of test suite - This script return non-zero if the executed test failed. exit $SUITE_EXIT_CODE diff --git a/Build/phpstan/phpstan-baseline.neon b/Build/phpstan/phpstan-baseline.neon new file mode 100644 index 0000000..fdb88ac --- /dev/null +++ b/Build/phpstan/phpstan-baseline.neon @@ -0,0 +1,46 @@ +parameters: + ignoreErrors: + - + message: "#^Call to sprintf contains 0 placeholders, 1 value given\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Call to static method getClassesInNamespace\\(\\) on an unknown class HaydenPierce\\\\ClassFinder\\\\ClassFinder\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Class T3docs\\\\Codesnippet\\\\Util\\\\Null_ not found\\.$#" + count: 17 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Static method T3docs\\\\Codesnippet\\\\Util\\\\ArrayHelper\\:\\:varExportArrayShort\\(\\) invoked with 2 parameters, 1 required\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Variable \\$description might not be defined\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Variable \\$paramName might not be defined\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Variable \\$shortClass might not be defined\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Variable \\$type might not be defined\\.$#" + count: 1 + path: ../../Classes/Util/ClassDocsHelper.php + + - + message: "#^Call to an undefined static method T3docs\\\\Codesnippet\\\\Util\\\\ClassDocsHelper\\:\\:extractDocsFromClass\\(\\)\\.$#" + count: 1 + path: ../../Classes/Util/Typo3CodeSnippets.php diff --git a/Build/phpstan/phpstan-typo3-constants.php b/Build/phpstan/phpstan-typo3-constants.php new file mode 100644 index 0000000..5b59c2e --- /dev/null +++ b/Build/phpstan/phpstan-typo3-constants.php @@ -0,0 +1,18 @@ +withPaths([ + __DIR__ . '/../../Classes', + __DIR__ . '/../../Configuration', + __DIR__ . '/../../*.php', + ]) + ->withPhpSets() + ->withSets([ + Typo3SetList::CODE_QUALITY, + Typo3SetList::GENERAL, + Typo3LevelSetList::UP_TO_TYPO3_13, + ]) + ->withImportNames(importShortClasses: false, removeUnusedImports: true) + // To have a better analysis from PHPStan, we teach it here some more things + ->withPHPStanConfigs([ + Typo3Option::PHPSTAN_FOR_RECTOR_PATH, + ]) + ->withRules([ + AddVoidReturnTypeWhereNoReturnRector::class, + ConvertImplicitVariablesToExplicitGlobalsRector::class, + ]) + ->withConfiguredRule(ExtEmConfRector::class, [ + ExtEmConfRector::TYPO3_VERSION_CONSTRAINT => '13.1.0-13.99.99', + ExtEmConfRector::ADDITIONAL_VALUES_TO_BE_REMOVED => [], + ]) + // If you use importNames(), you should consider excluding some TYPO3 files. + ->withSkip([ + // AddLiteralSeparatorToNumberRector would make the exception codes more readable. + // But as they are just timestamps this is not needed/wanted. + AddLiteralSeparatorToNumberRector::class, + ]) +; diff --git a/Build/testing-docker/docker-compose.yml b/Build/testing-docker/docker-compose.yml deleted file mode 100644 index 1243872..0000000 --- a/Build/testing-docker/docker-compose.yml +++ /dev/null @@ -1,147 +0,0 @@ -version: '2.3' -services: - cgl: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - PHP_CS_FIXER_IGNORE_ENV=1 php -dxdebug.mode=off \ - .Build/bin/php-cs-fixer fix \ - -v \ - ${CGLCHECK_DRY_RUN} \ - --config=Build/php-cs-fixer/.php-cs-fixer.dist.php \ - --using-cache=no . - " - - composer_update: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - environment: - COMPOSER_CACHE_DIR: ".Build/.cache/composer" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - - if [ ${TYPO3_VERSION} == "11.5" ]; then - composer rem --dev "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge" --no-update - composer req --dev --no-update \ - typo3/cms-composer-installers:^3.0 - composer req typo3/cms-core:^11.5 --no-update - fi - if [ ${TYPO3_VERSION} == "12.0" ]; then - composer req --dev --no-update \ - "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge":^0.0.1 - composer req typo3/cms-core:~12.0@dev -W --no-update - fi - if [ ${TYPO3_VERSION} == "main" ]; then - composer req --dev --no-update \ - "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge":^0.0.1 \ - typo3/cms-composer-installers:^5.0 \ - typo3/cms-backend:dev-main \ - typo3/cms-recordlist:dev-main \ - typo3/cms-frontend:dev-main \ - typo3/cms-extbase:dev-main \ - typo3/cms-fluid:dev-main \ - typo3/cms-install:dev-main - composer req typo3/cms-core:dev-main -W --no-update - fi - - composer update --no-progress --no-interaction; - " - - composer_validate: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - environment: - COMPOSER_CACHE_DIR: ".Build/.cache/composer" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - composer validate --no-check-lock; - " - - composer_normalize: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - environment: - COMPOSER_CACHE_DIR: ".Build/.cache/composer" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - composer normalize --no-check-lock --no-update-lock ${COMPOSER_NORMALIZE_DRY_RUN}; - " - - lint: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - find . -name \\*.php ! -path "./.Build/\\*" -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null - " - - unit: - image: typo3/core-testing-${DOCKER_PHP_IMAGE}:latest - user: "${HOST_UID}" - volumes: - - ${ROOT_DIR}:${ROOT_DIR} - working_dir: ${ROOT_DIR} - extra_hosts: - - "host.docker.internal:host-gateway" - command: > - /bin/sh -c " - if [ ${SCRIPT_VERBOSE} -eq 1 ]; then - set -x - fi - php -v | grep '^PHP'; - if [ ${PHP_XDEBUG_ON} -eq 0 ]; then - XDEBUG_MODE=\"off\" \ - .Build/bin/phpunit -c Build/php-unit/UnitTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; - else - XDEBUG_MODE=\"debug,develop\" \ - XDEBUG_TRIGGER=\"foo\" \ - XDEBUG_CONFIG=\"client_port=${PHP_XDEBUG_PORT} client_host=host.docker.internal\" \ - .Build/bin/phpunit -c Build/php-unit/UnitTests.xml ${EXTRA_TEST_OPTIONS} ${TEST_FILE}; - fi - " diff --git a/Classes/Exceptions/ClassNotPublicException.php b/Classes/Exceptions/ClassNotPublicException.php index 2603843..c8b4aca 100644 --- a/Classes/Exceptions/ClassNotPublicException.php +++ b/Classes/Exceptions/ClassNotPublicException.php @@ -17,6 +17,4 @@ namespace T3docs\Codesnippet\Exceptions; -class ClassNotPublicException extends \TYPO3\CMS\Core\Exception -{ -} +class ClassNotPublicException extends \TYPO3\CMS\Core\Exception {} diff --git a/Classes/Exceptions/InvalidConfigurationException.php b/Classes/Exceptions/InvalidConfigurationException.php index 879bd57..42594e7 100644 --- a/Classes/Exceptions/InvalidConfigurationException.php +++ b/Classes/Exceptions/InvalidConfigurationException.php @@ -17,6 +17,4 @@ namespace T3docs\Codesnippet\Exceptions; -class InvalidConfigurationException extends \TYPO3\CMS\Core\Exception -{ -} +class InvalidConfigurationException extends \TYPO3\CMS\Core\Exception {} diff --git a/Classes/Util/ArrayHelper.php b/Classes/Util/ArrayHelper.php index 2cb3e7b..75659bc 100644 --- a/Classes/Util/ArrayHelper.php +++ b/Classes/Util/ArrayHelper.php @@ -85,7 +85,7 @@ protected static function extractFieldFromArray(array $array, string $field): ar $path = str_getcsv($field, '/'); $pathReverse = array_reverse($path); - for ($i=0; $i < count($pathReverse); $i++) { + for ($i = 0; $i < count($pathReverse); $i++) { if ($i === 0) { $result = [$pathReverse[$i] => $value]; } else { diff --git a/Classes/Util/ClassDocsHelper.php b/Classes/Util/ClassDocsHelper.php index 47336fa..b2d013f 100644 --- a/Classes/Util/ClassDocsHelper.php +++ b/Classes/Util/ClassDocsHelper.php @@ -97,7 +97,7 @@ public static function extractPhpDomainAll( } $classPartArray = explode('\\', $class); if (count($classPartArray) > 1) { - $shortClass = $classPartArray[count($classPartArray) -1]; + $shortClass = $classPartArray[count($classPartArray) - 1]; } $extractPhpDomainConfig = [ 'class' => $class, @@ -437,7 +437,7 @@ public static function getUseStatements(string $class): string $startLineBody = $classReflection->getStartLine(); $result = []; - for ($lineNumber=0; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = 0; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); $line = $splFileObject->current(); if (preg_match('#^use [^;]*;#', $line) === 1) { @@ -490,11 +490,10 @@ public static function getClassSignature( string $class, bool $withCode, \ReflectionClass $reflectionClass, - $gitHubLink='', - $includeClassComment=true, + $gitHubLink = '', + $includeClassComment = true, $noindexInClass = false, - ): string - { + ): string { $classReflection = self::getClassReflection($class); $docBlockFactory = self::getDocBlockFactory(); @@ -531,11 +530,11 @@ public static function getClassSignature( } else { $result[] = sprintf('.. php:class:: %s', $classShortName); } - if($noindexInClass) { - $result[] = "\n".' :noindex:'; + if ($noindexInClass) { + $result[] = "\n" . ' :noindex:'; } if ($reflectionClass->isAbstract() && !$reflectionClass->isInterface()) { - $result[] = "\n".' :abstract:'; + $result[] = "\n" . ' :abstract:'; } $result[] = "\n\n"; if ($comment) { @@ -606,7 +605,7 @@ public static function getMethodCode( (!$allowInternal && $isInternal) or (!$allowDeprecated && $methodReflection->isDeprecated()) or (($modifierSum & $methodReflection->getModifiers()) == 0) - or (!$includeConstructor && $method=='__construct') + or (!$includeConstructor && $method == '__construct') ) { return ''; } @@ -621,9 +620,9 @@ public static function getMethodCode( $endLineBody = $methodReflection->getEndLine(); $startLineSignature = max($startLineBody - 20, 0); - for ($lineNumber=$startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); - if (strpos($splFileObject->current(), sprintf('function %s', RstHelper::escapeRst($method))) !== false) { + if (str_contains($splFileObject->current(), sprintf('function %s', RstHelper::escapeRst($method)))) { $startLineSignature = $lineNumber; } } @@ -728,7 +727,7 @@ public static function getMethodCode( } $codeResult = []; if ($withCode) { - for ($lineNumber=$startLineSignature; $lineNumber < $endLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber < $endLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); $codeResult[] = $splFileObject->current(); } diff --git a/Classes/Util/ClassHelper.php b/Classes/Util/ClassHelper.php index f227ed9..4b51635 100644 --- a/Classes/Util/ClassHelper.php +++ b/Classes/Util/ClassHelper.php @@ -159,7 +159,7 @@ public static function getUseStatements(string $class): string $startLineBody = $classReflection->getStartLine(); $result = []; - for ($lineNumber=0; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = 0; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); $line = $splFileObject->current(); if (preg_match('#^use [^;]*;#', $line) === 1) { @@ -219,9 +219,9 @@ public static function getClassSignature(string $class, bool $withComment = fals $endLineBody = $classReflection->getEndLine(); $startLineSignature = max($startLineBody - 20, 0); - for ($lineNumber=$startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); - if (strpos($splFileObject->current(), sprintf('class %s', $classShortName)) !== false) { + if (str_contains($splFileObject->current(), sprintf('class %s', $classShortName))) { $startLineSignature = $lineNumber; } } @@ -230,12 +230,12 @@ public static function getClassSignature(string $class, bool $withComment = fals if ($withComment && $classReflection->getDocComment() !== false) { $result[] = self::fixDocCommentIndentation($classReflection->getDocComment()) . "\n"; } - for ($lineNumber=$startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); $result[] = $splFileObject->current(); } $result[] = '%s' . "\n"; - $splFileObject->seek($endLineBody-1); + $splFileObject->seek($endLineBody - 1); $result[] = $splFileObject->current(); // SplFileObject locks the file, so null it when no longer needed @@ -292,9 +292,9 @@ public static function getMethodCode(string $class, string $method, bool $withCo $endLineBody = $methodReflection->getEndLine(); $startLineSignature = max($startLineBody - 20, 0); - for ($lineNumber=$startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber <= $startLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); - if (strpos($splFileObject->current(), sprintf('function %s', $method)) !== false) { + if (str_contains($splFileObject->current(), sprintf('function %s', $method))) { $startLineSignature = $lineNumber; } } @@ -303,7 +303,7 @@ public static function getMethodCode(string $class, string $method, bool $withCo if ($withComment && $methodReflection->getDocComment() !== false) { $result[] = self::fixDocCommentIndentation($methodReflection->getDocComment()) . "\n"; } - for ($lineNumber=$startLineSignature; $lineNumber < $endLineBody; $lineNumber++) { + for ($lineNumber = $startLineSignature; $lineNumber < $endLineBody; $lineNumber++) { $splFileObject->seek($lineNumber); $result[] = $splFileObject->current(); } diff --git a/Classes/Util/CodeSnippetCreator.php b/Classes/Util/CodeSnippetCreator.php index a7d4633..ea5fd8a 100644 --- a/Classes/Util/CodeSnippetCreator.php +++ b/Classes/Util/CodeSnippetCreator.php @@ -30,8 +30,8 @@ class CodeSnippetCreator { - const RECURSIVE_PATH = 1; - const FLAT_PATH = 1; + public const RECURSIVE_PATH = 1; + public const FLAT_PATH = 1; private static $fileCount = 0; private static $configPath = ''; diff --git a/Classes/Util/FileHelper.php b/Classes/Util/FileHelper.php index 24aa5e5..9df2388 100644 --- a/Classes/Util/FileHelper.php +++ b/Classes/Util/FileHelper.php @@ -137,7 +137,7 @@ public static function deleteRecursively(string $path): void */ public static function getRealPath(string $path): string { - return strpos($path, 'vfs://') === 0 ? $path : realpath($path); + return str_starts_with($path, 'vfs://') ? $path : realpath($path); } /** @@ -172,7 +172,7 @@ public static function getPathBySegments(string ...$segments): string public static function isAbsolutePath(string $path): bool { - return strpos($path, '://') !== false || strpos($path, DIRECTORY_SEPARATOR) === 0; + return str_contains($path, '://') || str_starts_with($path, DIRECTORY_SEPARATOR); } /** @@ -207,6 +207,6 @@ public static function getUrlBySegments(string ...$segments): string public static function isAbsoluteUrl(string $url): bool { - return strpos($url, '://') !== false || strpos($url, '/') === 0; + return str_contains($url, '://') || str_starts_with($url, '/'); } } diff --git a/Classes/Util/JsonHelper.php b/Classes/Util/JsonHelper.php index 19e4f3d..be1570d 100644 --- a/Classes/Util/JsonHelper.php +++ b/Classes/Util/JsonHelper.php @@ -88,7 +88,7 @@ protected static function grabInlineJsonsAndReplaceWithPlaceholders( foreach ($jsonEntry as $key => &$child) { self::grabInlineJsonsAndReplaceWithPlaceholders( $child, - $inlineLevel-1, + $inlineLevel - 1, $inlineJsons, array_merge($keys, [$key]) ); diff --git a/Classes/Util/Typo3CodeSnippets.php b/Classes/Util/Typo3CodeSnippets.php index 9bec151..e928937 100644 --- a/Classes/Util/Typo3CodeSnippets.php +++ b/Classes/Util/Typo3CodeSnippets.php @@ -117,7 +117,7 @@ private function shortenFirstPhpComment(string $code): string * This file is part of the TYPO3 CMS project. [...] */ ', $code - )??$code; + ) ?? $code; } /** diff --git a/Tests/Unit/Service/TestClasses/MyFirstClass.php b/Tests/Unit/Service/TestClasses/MyFirstClass.php index f910ed0..7b1d7e9 100644 --- a/Tests/Unit/Service/TestClasses/MyFirstClass.php +++ b/Tests/Unit/Service/TestClasses/MyFirstClass.php @@ -17,7 +17,5 @@ class MyFirstClass { - public function __construct() - { - } + public function __construct() {} } diff --git a/Tests/Unit/Service/TestClasses/MySecondClass.php b/Tests/Unit/Service/TestClasses/MySecondClass.php index 09f552f..3c1d171 100644 --- a/Tests/Unit/Service/TestClasses/MySecondClass.php +++ b/Tests/Unit/Service/TestClasses/MySecondClass.php @@ -17,7 +17,5 @@ class MySecondClass { - public function __construct() - { - } + public function __construct() {} } diff --git a/composer.json b/composer.json index 94149c8..1bc80fb 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "t3docs/codesnippet", "description": "This extension packages creates restructured files to document the API", "license": [ - "GPL-2.0+" + "GPL-2.0-or-later" ], "type": "typo3-cms-extension", "authors": [ @@ -14,12 +14,13 @@ "require": { "php": "^8.1", "symfony/console": "^6.4 || ^7.0", - "typo3/cms-core": "^12.4 || ^13.0 || dev-main" + "typo3/cms-core": "^12.4 || ^13.0 || ^13.1 || dev-main" }, "require-dev": { "ergebnis/composer-normalize": "^2.42", - "typo3/coding-standards": "^0.7.1", - "typo3/testing-framework": "^8.0" + "phpstan/phpstan": "^1.10", + "typo3/coding-standards": "dev-main", + "typo3/testing-framework": "^8.0.9" }, "autoload": { "psr-4": { @@ -33,10 +34,10 @@ }, "config": { "allow-plugins": { - "typo3/cms-composer-installers": true, - "typo3/class-alias-loader": true, "ergebnis/composer-normalize": true, - "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge": true + "sbuerk/typo3-cmscomposerinstallers-testingframework-bridge": true, + "typo3/class-alias-loader": true, + "typo3/cms-composer-installers": true }, "bin-dir": ".Build/bin", "sort-packages": true,