diff --git a/.gitattributes b/.gitattributes
index c38382e..779ec05 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,7 @@
+/.github/ export-ignore
/Build/ export-ignore
-/Resources/Private/Php/ export-ignore
+/Tests/ export-ignore
+/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
-/.editorconfig export-ignore
+/.crowdin.yml export-ignore
\ No newline at end of file
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5891ce5..4b821c6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,54 +1,22 @@
-# Adapted from https://github.com/TYPO3GmbH/blog/blob/master/.github/workflows/ci.yml
-name: CI
+name: Tests
-on: [pull_request]
+on: pull_request
jobs:
- build:
- runs-on: ubuntu-latest
+ CGL:
+ name: Coding Style Check (TYPO3 Community CGL)
- strategy:
- fail-fast: false
- matrix:
- typo3: [^10.4, ^11.5]
- php: ['7.4']
- include:
- - typo3: ^11.5
- php: '8.0'
- - typo3: ^11.5
- php: '8.1'
+ runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v2
-
- - name: Setup PHP ${{ matrix.php }}, with composer and extensions
- uses: shivammathur/setup-php@v2
- with:
- php-version: ${{ matrix.php }}
- extensions: mbstring, dom, zip
-
- - name: Validate composer.json and composer.lock
- run: composer validate
+ uses: actions/checkout@v4
- - name: Get composer cache directory
- id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
-
- - name: Cache composer dependencies
- uses: actions/cache@v2
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
- restore-keys: ${{ runner.os }}-composer-
-
- - name: Install dependencies with typo3/cms-core:${{ matrix.typo3 }}
- run: |
- composer require typo3/cms-core:${{ matrix.typo3 }} --no-progress
- git checkout composer.json
-
- - name: php-cs-fixer
- run: composer ci:php:fixer
+ - name: Composer
+ run: Build/Scripts/runTests.sh -p 8.1 -s composerUpdate
- name: Lint PHP
- run: composer ci:php:lint
+ run: Build/Scripts/runTests.sh -p 8.1 -s lint
+
+ - name: Validate code against CGL
+ run: Build/Scripts/runTests.sh -p 8.1 -s cgl -n
diff --git a/.gitignore b/.gitignore
index 42796e9..63300ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,17 +1,48 @@
-# Git global ignore file
-# for local exclude patterns please edit .git/info/exclude
-# Example file see https://github.com/TYPO3-Documentation/T3DocTeam/blob/master/.gitignore
+########################
+# plesk-widget
+# global ignore file
+########################
-# ignore generated documentation
+# Ignore files generated by docs rendering
*GENERATED*
+docker-compose.yaml
+docker-compose.yml
-# ignore typical clutter of IDEs and editors (this could be added in .git/info/exclude,
-# but we add it here for convenience)
+# Ignore environment files
+.env
+
+# Ignore temporary files (left by editors and OS)
*~
*.bak
+*.swp
+.DS_Store
+
+# Ignore by common IDEs used directories/files
+nbproject
*.idea
*.project
-*.swp
-.project
+.buildpath
+.settings
+.TemporaryItems
.webprj
+.fleet
+
+# Temporary files and folders
+/.cache
+.php_cs.cache
+.php-cs-fixer.cache
+.sass-cache
+.session
+*.log
+
+# Ignore composer stuff
+bin/*
+vendor/*
+.build
+.php_cs.cache
+composer.lock
+# Ignore testing stuff
+/.Build
+/composer.json.orig
+/composer.json.testing
diff --git a/Build/FunctionalTests.xml b/Build/FunctionalTests.xml
new file mode 100644
index 0000000..59a41b6
--- /dev/null
+++ b/Build/FunctionalTests.xml
@@ -0,0 +1,28 @@
+
+
+
+ ../Tests/Functional/
+
+
+
+
+
+
+
diff --git a/Build/FunctionalTestsBootstrap.php b/Build/FunctionalTestsBootstrap.php
new file mode 100644
index 0000000..8bad2c5
--- /dev/null
+++ b/Build/FunctionalTestsBootstrap.php
@@ -0,0 +1,17 @@
+defineOriginalRootPath();
+ $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/tests');
+ $testbase->createDirectory(ORIGINAL_ROOT . 'typo3temp/var/transient');
+});
diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh
new file mode 100755
index 0000000..e8f2f11
--- /dev/null
+++ b/Build/Scripts/runTests.sh
@@ -0,0 +1,606 @@
+#!/usr/bin/env bash
+
+#
+# EXT:examples test runner based on docker/podman.
+#
+
+trap 'cleanUp;exit 2' SIGINT
+
+waitFor() {
+ local HOST=${1}
+ local PORT=${2}
+ local TESTCOMMAND="
+ COUNT=0;
+ while ! nc -z ${HOST} ${PORT}; do
+ if [ \"\${COUNT}\" -gt 10 ]; then
+ echo \"Can not connect to ${HOST} port ${PORT}. Aborting.\";
+ exit 1;
+ fi;
+ sleep 1;
+ COUNT=\$((COUNT + 1));
+ done;
+ "
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name wait-for-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_ALPINE} /bin/sh -c "${TESTCOMMAND}"
+ if [[ $? -gt 0 ]]; then
+ kill -SIGINT -$$
+ fi
+}
+
+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
+}
+
+cleanCacheFiles() {
+ echo -n "Clean caches ... "
+ rm -rf \
+ .Build/.cache \
+ .php-cs-fixer.cache
+ echo "done"
+}
+
+cleanRenderedDocumentationFiles() {
+ echo -n "Clean rendered documentation files ... "
+ rm -rf \
+ Documentation-GENERATED-temp
+ echo "done"
+}
+
+handleDbmsOptions() {
+ # -a, -d, -i depend on each other. Validate input combinations and set defaults.
+ case ${DBMS} in
+ mariadb)
+ [ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli"
+ if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then
+ echo "Invalid combination -d ${DBMS} -a ${DATABASE_DRIVER}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ [ -z "${DBMS_VERSION}" ] && DBMS_VERSION="10.4"
+ if ! [[ ${DBMS_VERSION} =~ ^(10.4|10.5|10.6|10.7|10.8|10.9|10.10|10.11|11.0|11.1)$ ]]; then
+ echo "Invalid combination -d ${DBMS} -i ${DBMS_VERSION}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ ;;
+ mysql)
+ [ -z "${DATABASE_DRIVER}" ] && DATABASE_DRIVER="mysqli"
+ if [ "${DATABASE_DRIVER}" != "mysqli" ] && [ "${DATABASE_DRIVER}" != "pdo_mysql" ]; then
+ echo "Invalid combination -d ${DBMS} -a ${DATABASE_DRIVER}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ [ -z "${DBMS_VERSION}" ] && DBMS_VERSION="8.0"
+ if ! [[ ${DBMS_VERSION} =~ ^(8.0|8.1|8.2|8.3)$ ]]; then
+ echo "Invalid combination -d ${DBMS} -i ${DBMS_VERSION}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ ;;
+ postgres)
+ if [ -n "${DATABASE_DRIVER}" ]; then
+ echo "Invalid combination -d ${DBMS} -a ${DATABASE_DRIVER}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ [ -z "${DBMS_VERSION}" ] && DBMS_VERSION="10"
+ if ! [[ ${DBMS_VERSION} =~ ^(10|11|12|13|14|15|16)$ ]]; then
+ echo "Invalid combination -d ${DBMS} -i ${DBMS_VERSION}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ ;;
+ sqlite)
+ if [ -n "${DATABASE_DRIVER}" ]; then
+ echo "Invalid combination -d ${DBMS} -a ${DATABASE_DRIVER}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ if [ -n "${DBMS_VERSION}" ]; then
+ echo "Invalid combination -d ${DBMS} -i ${DATABASE_DRIVER}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ echo "Invalid option -d ${DBMS}" >&2
+ echo >&2
+ echo "Use \".Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
+ exit 1
+ ;;
+ esac
+}
+
+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: 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
+ - composerUpdateRector: "composer update", for rector subdirectory
+ - composerValidate: "composer validate"
+ - functional: PHP functional tests
+ - lint: PHP linting
+ - phpstan: PHPStan static analysis
+ - phpstanBaseline: Generate PHPStan baseline
+ - unit: PHP unit tests
+ - rector: Apply Rector rules
+ - renderDocumentation
+ - testRenderDocumentation
+
+ -b
+ Container environment:
+ - docker
+ - podman
+
+ If not specified, podman will be used if available. Otherwise, docker is used.
+
+ -a
+ Only with -s functional|functionalDeprecated
+ Specifies to use another driver, following combinations are available:
+ - mysql
+ - mysqli (default)
+ - pdo_mysql
+ - mariadb
+ - mysqli (default)
+ - pdo_mysql
+
+ -d
+ Only with -s functional|functionalDeprecated|acceptance|acceptanceComposer|acceptanceInstall
+ Specifies on which DBMS tests are performed
+ - sqlite: (default): use sqlite
+ - mariadb: use mariadb
+ - mysql: use MySQL
+ - postgres: use postgres
+
+ -i version
+ Specify a specific database version
+ With "-d mariadb":
+ - 10.4 short-term, maintained until 2024-06-18 (default)
+ - 10.5 short-term, maintained until 2025-06-24
+ - 10.6 long-term, maintained until 2026-06
+ - 10.7 short-term, no longer maintained
+ - 10.8 short-term, maintained until 2023-05
+ - 10.9 short-term, maintained until 2023-08
+ - 10.10 short-term, maintained until 2023-11
+ - 10.11 long-term, maintained until 2028-02
+ - 11.0 development series
+ - 11.1 short-term development series
+ With "-d mysql":
+ - 8.0 maintained until 2026-04 (default) LTS
+ - 8.1 unmaintained since 2023-10
+ - 8.2 unmaintained since 2024-01
+ - 8.3 maintained until 2024-04
+ With "-d postgres":
+ - 10 unmaintained since 2022-11-10 (default)
+ - 11 unmaintained since 2023-11-09
+ - 12 maintained until 2024-11-14
+ - 13 maintained until 2025-11-13
+ - 14 maintained until 2026-11-12
+ - 15 maintained until 2027-11-11
+ - 16 maintained until 2028-11-09
+
+ -p <8.1|8.2|8.3>
+ Specifies the PHP minor version to be used
+ - 8.1: use PHP 8.1
+ - 8.2: use PHP 8.2
+ - 8.3: use PHP 8.3
+
+ -x
+ Only with -s functional|unit
+ 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, 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 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.
+
+Examples:
+ # Run unit tests using PHP 8.2
+ ./Build/Scripts/runTests.sh -p 8.2 -s unit
+
+ # Run functional tests using PHP 8.3 and MariaDB 10.6 using pdo_mysql
+ ./Build/Scripts/runTests.sh -p 8.3 -s functional -d mariadb -i 10.6 -a pdo_mysql
+
+ # Run functional tests on postgres with xdebug, php 8.3 and execute a restricted set of tests
+ ./Build/Scripts/runTests.sh -x -p 8.3 -s functional -d postgres -- Tests/Functional/DummyTest.php
+EOF
+}
+
+# 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
+
+# Option defaults
+# @todo Consider to switch from cgl to help as default
+TEST_SUITE="cgl"
+DATABASE_DRIVER=""
+DBMS="sqlite"
+DBMS_VERSION=""
+PHP_VERSION="8.1"
+PHP_XDEBUG_ON=0
+PHP_XDEBUG_PORT=9003
+CGLCHECK_DRY_RUN=0
+CI_PARAMS="${CI_PARAMS:-}"
+DOCS_PARAMS="${DOCS_PARAMS:=--pull always}"
+CONTAINER_BIN=""
+CONTAINER_HOST="host.docker.internal"
+
+# 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)
+while getopts "a:b:d:i:s:p:xy:nhu" OPT; do
+ case ${OPT} in
+ a)
+ DATABASE_DRIVER=${OPTARG}
+ ;;
+ s)
+ TEST_SUITE=${OPTARG}
+ ;;
+ b)
+ if ! [[ ${OPTARG} =~ ^(docker|podman)$ ]]; then
+ INVALID_OPTIONS+=("${OPTARG}")
+ fi
+ CONTAINER_BIN=${OPTARG}
+ ;;
+ d)
+ DBMS=${OPTARG}
+ ;;
+ i)
+ DBMS_VERSION=${OPTARG}
+ ;;
+ p)
+ PHP_VERSION=${OPTARG}
+ if ! [[ ${PHP_VERSION} =~ ^(8.1|8.2|8.3)$ ]]; then
+ INVALID_OPTIONS+=("p ${OPTARG}")
+ fi
+ ;;
+ x)
+ PHP_XDEBUG_ON=1
+ ;;
+ 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}")
+ ;;
+ esac
+done
+
+# Exit on invalid options
+if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then
+ echo "Invalid option(s):" >&2
+ for I in "${INVALID_OPTIONS[@]}"; do
+ echo "-"${I} >&2
+ done
+ echo >&2
+ echo "call \".Build/Scripts/runTests.sh -h\" to display help and valid options"
+ exit 1
+fi
+
+handleDbmsOptions
+
+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_MARIADB="docker.io/mariadb:${DBMS_VERSION}"
+IMAGE_MYSQL="docker.io/mysql:${DBMS_VERSION}"
+IMAGE_POSTGRES="docker.io/postgres:${DBMS_VERSION}-alpine"
+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))
+
+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 [ ${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=${CONTAINER_HOST}"
+fi
+
+# Suite execution
+case ${TEST_SUITE} in
+ cgl)
+ if [ "${CGLCHECK_DRY_RUN}" -eq 1 ]; then
+ COMMAND="php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v --dry-run --diff --config=Build/cgl/.php-cs-fixer.dist.php --using-cache=no ."
+ else
+ COMMAND="php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v --config=Build/cgl/.php-cs-fixer.dist.php --using-cache=no ."
+ fi
+ ${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=$?
+ ;;
+ clean)
+ 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)
+ if [ "${CGLCHECK_DRY_RUN}" -eq 1 ]; then
+ COMMAND=(composer normalize -n)
+ else
+ COMMAND=(composer normalize)
+ 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=$?
+ ;;
+ composerUpdate)
+ 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
+ COMMAND=(composer require --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=$?
+ cp ${ROOT_DIR}/composer.json ${ROOT_DIR}/composer.json.testing
+ mv ${ROOT_DIR}/composer.json.orig ${ROOT_DIR}/composer.json
+ ;;
+ composerUpdateRector)
+ rm -rf Build/rector/.Build/bin/ Build/rector/.Build/vendor Build/rector/composer.lock
+ cp ${ROOT_DIR}/Build/rector/composer.json ${ROOT_DIR}/Build/rector/composer.json.orig
+ if [ -f "${ROOT_DIR}/Build/rector/composer.json.testing" ]; then
+ cp ${ROOT_DIR}/Build/rector/composer.json ${ROOT_DIR}/Build/rector/composer.json.orig
+ fi
+ COMMAND=(composer require --working-dir=${ROOT_DIR}/Build/rector --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=$?
+ cp ${ROOT_DIR}/Build/rector/composer.json ${ROOT_DIR}/Build/rector/composer.json.testing
+ mv ${ROOT_DIR}/Build/rector/composer.json.orig ${ROOT_DIR}/Build/rector/composer.json
+ ;;
+ composerValidate)
+ COMMAND=(composer validate "$@")
+ ${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=$?
+ ;;
+ functional)
+ CONTAINER_PARAMS=""
+ COMMAND=(.Build/bin/phpunit -c Build/phpunit/FunctionalTests.xml --exclude-group not-${DBMS} ${EXTRA_TEST_OPTIONS} "$@")
+ case ${DBMS} in
+ mariadb)
+ echo "Using driver: ${DATABASE_DRIVER}"
+ ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mariadb-func-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=funcp --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MARIADB} >/dev/null
+ waitFor mariadb-func-${SUFFIX} 3306
+ CONTAINERPARAMS="-e typo3DatabaseDriver=${DATABASE_DRIVER} -e typo3DatabaseName=func_test -e typo3DatabaseUsername=root -e typo3DatabaseHost=mariadb-func-${SUFFIX} -e typo3DatabasePassword=funcp"
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND[@]}"
+ SUITE_EXIT_CODE=$?
+ ;;
+ mysql)
+ echo "Using driver: ${DATABASE_DRIVER}"
+ ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name mysql-func-${SUFFIX} --network ${NETWORK} -d -e MYSQL_ROOT_PASSWORD=funcp --tmpfs /var/lib/mysql/:rw,noexec,nosuid ${IMAGE_MYSQL} >/dev/null
+ waitFor mysql-func-${SUFFIX} 3306
+ CONTAINERPARAMS="-e typo3DatabaseDriver=${DATABASE_DRIVER} -e typo3DatabaseName=func_test -e typo3DatabaseUsername=root -e typo3DatabaseHost=mysql-func-${SUFFIX} -e typo3DatabasePassword=funcp"
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND[@]}"
+ SUITE_EXIT_CODE=$?
+ ;;
+ postgres)
+ ${CONTAINER_BIN} run --rm ${CI_PARAMS} --name postgres-func-${SUFFIX} --network ${NETWORK} -d -e POSTGRES_PASSWORD=funcp -e POSTGRES_USER=funcu --tmpfs /var/lib/postgresql/data:rw,noexec,nosuid ${IMAGE_POSTGRES} >/dev/null
+ waitFor postgres-func-${SUFFIX} 5432
+ CONTAINERPARAMS="-e typo3DatabaseDriver=pdo_pgsql -e typo3DatabaseName=bamboo -e typo3DatabaseUsername=funcu -e typo3DatabaseHost=postgres-func-${SUFFIX} -e typo3DatabasePassword=funcp"
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND[@]}"
+ SUITE_EXIT_CODE=$?
+ ;;
+ sqlite)
+ # create sqlite tmpfs mount typo3temp/var/tests/functional-sqlite-dbs/ to avoid permission issues
+ mkdir -p "${ROOT_DIR}/.Build/web/typo3temp/var/tests/functional-sqlite-dbs/"
+ CONTAINERPARAMS="-e typo3DatabaseDriver=pdo_sqlite --tmpfs ${ROOT_DIR}/.Build/web/typo3temp/var/tests/functional-sqlite-dbs/:rw,noexec,nosuid"
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name functional-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${CONTAINERPARAMS} ${IMAGE_PHP} "${COMMAND[@]}"
+ SUITE_EXIT_CODE=$?
+ ;;
+ esac
+ ;;
+ 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=$?
+ ;;
+ 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/rector/.Build/bin/rector -n --config=Build/rector/rector.php --clear-cache "$@")
+ else
+ COMMAND=(php -dxdebug.mode=off Build/rector/.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=$?
+ ;;
+ unit)
+ COMMAND=(.Build/bin/phpunit -c Build/phpunit/UnitTests.xml ${EXTRA_TEST_OPTIONS} "$@")
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG="${XDEBUG_CONFIG}" ${IMAGE_PHP} "${COMMAND[@]}"
+ SUITE_EXIT_CODE=$?
+ ;;
+ update)
+ # 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 )
+ 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 ""
+ ;;
+ *)
+ 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 [[ ${TEST_SUITE} =~ ^functional$ ]]; then
+ case "${DBMS}" in
+ mariadb|mysql)
+ echo "DBMS: ${DBMS} version ${DBMS_VERSION} driver ${DATABASE_DRIVER}" >&2
+ ;;
+ postgres)
+ echo "DBMS: ${DBMS} version ${DBMS_VERSION} driver pdo_pgsql" >&2
+ ;;
+ sqlite)
+ echo "DBMS: ${DBMS} driver pdo_sqlite" >&2
+ ;;
+ esac
+fi
+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
\ No newline at end of file
diff --git a/Build/UnitTests.xml b/Build/UnitTests.xml
new file mode 100644
index 0000000..a90da4c
--- /dev/null
+++ b/Build/UnitTests.xml
@@ -0,0 +1,29 @@
+
+
+
+ ../Tests/Unit/
+
+
+
+
+
+
+
diff --git a/Build/UnitTestsBootstrap.php b/Build/UnitTestsBootstrap.php
new file mode 100644
index 0000000..8a8c307
--- /dev/null
+++ b/Build/UnitTestsBootstrap.php
@@ -0,0 +1,75 @@
+getWebRoot(), '/'));
+ }
+ if (!getenv('TYPO3_PATH_WEB')) {
+ putenv('TYPO3_PATH_WEB=' . rtrim($testbase->getWebRoot(), '/'));
+ }
+
+ $testbase->defineSitePath();
+
+ // We can use the "typo3/cms-composer-installers" constant "TYPO3_COMPOSER_MODE" to determine composer mode.
+ // This should be always true except for TYPO3 mono repository.
+ $composerMode = defined('TYPO3_COMPOSER_MODE') && TYPO3_COMPOSER_MODE === true;
+ $requestType = \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_BE | \TYPO3\CMS\Core\Core\SystemEnvironmentBuilder::REQUESTTYPE_CLI;
+ SystemEnvironmentBuilder::run(0, $requestType, $composerMode);
+
+ $testbase->createDirectory(Environment::getPublicPath() . '/typo3conf/ext');
+ $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/assets');
+ $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/var/tests');
+ $testbase->createDirectory(Environment::getPublicPath() . '/typo3temp/var/transient');
+
+ // Retrieve an instance of class loader and inject to core bootstrap
+ $classLoader = require $testbase->getPackagesPath() . '/autoload.php';
+ Bootstrap::initializeClassLoader($classLoader);
+
+ // Initialize default TYPO3_CONF_VARS
+ $configurationManager = new ConfigurationManager();
+ $GLOBALS['TYPO3_CONF_VARS'] = $configurationManager->getDefaultConfiguration();
+
+ $cache = new PhpFrontend(
+ 'core',
+ new NullBackend('production', [])
+ );
+ $packageManager = Bootstrap::createPackageManager(
+ UnitTestPackageManager::class,
+ Bootstrap::createPackageCache($cache)
+ );
+
+ GeneralUtility::setSingletonInstance(PackageManager::class, $packageManager);
+ ExtensionManagementUtility::setPackageManager($packageManager);
+
+ $testbase->dumpClassLoadingInformation();
+
+ GeneralUtility::purgeInstances();
+})();
diff --git a/Build/.php_cs.php b/Build/cgl/.php-cs-fixer.dist.php
similarity index 67%
rename from Build/.php_cs.php
rename to Build/cgl/.php-cs-fixer.dist.php
index cb8f19e..c5d37fd 100644
--- a/Build/.php_cs.php
+++ b/Build/cgl/.php-cs-fixer.dist.php
@@ -1,21 +1,17 @@
name('*.php')
->exclude('.build')
- ->exclude('var')
->in(__DIR__);
-$config = new PhpCsFixer\Config();
-return $config
+return (new Config())
+ ->setFinder($finder)
->setRiskyAllowed(true)
->setRules([
'@DoctrineAnnotation' => true,
- '@PSR2' => true,
+ '@PER' => true,
'header_comment' => [
- 'header' => $headerComment
+ 'header' => $headerComment,
],
+ 'no_superfluous_phpdoc_tags' => true,
'array_syntax' => ['syntax' => 'short'],
'blank_line_after_opening_tag' => true,
'braces' => ['allow_single_line_closure' => true],
@@ -50,9 +46,11 @@
'concat_space' => ['spacing' => 'one'],
'declare_equal_normalize' => ['space' => 'none'],
'dir_constant' => true,
+ 'function_to_constant' => ['functions' => ['get_called_class', 'get_class', 'get_class_this', 'php_sapi_name', 'phpversion', 'pi']],
'function_typehint_space' => true,
'lowercase_cast' => true,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
+ 'modernize_strpos' => true,
'modernize_types_casting' => true,
'native_function_casing' => true,
'new_with_braces' => true,
@@ -67,13 +65,14 @@
'no_short_bool_cast' => true,
'no_singleline_whitespace_before_semicolons' => true,
'no_superfluous_elseif' => true,
- 'no_trailing_comma_in_singleline_array' => true,
+ 'no_trailing_comma_in_singleline' => true,
'no_unneeded_control_parentheses' => true,
'no_unused_imports' => true,
'no_useless_else' => true,
+ 'no_useless_nullsafe_operator' => true,
'no_whitespace_in_blank_line' => true,
'ordered_imports' => true,
- 'php_unit_construct' => true,
+ 'php_unit_construct' => ['assertions' => ['assertEquals', 'assertSame', 'assertNotEquals', 'assertNotSame']],
'php_unit_mock_short_will_return' => true,
'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
'phpdoc_no_access' => true,
@@ -84,9 +83,10 @@
'phpdoc_types' => true,
'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
'return_type_declaration' => ['space_before' => 'none'],
- 'single_line_comment_style' => false,
'single_quote' => true,
+ 'single_line_comment_style' => ['comment_types' => ['hash']],
'single_trait_insert_per_statement' => true,
- 'whitespace_after_comma_in_array' => true
- ])
- ->setFinder($finder);
+ 'trailing_comma_in_multiline' => ['elements' => ['arrays']],
+ 'whitespace_after_comma_in_array' => ['ensure_single_space' => true],
+ 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false],
+ ]);
diff --git a/Classes/Client/ExtensionSettingException.php b/Classes/Client/ExtensionSettingException.php
new file mode 100644
index 0000000..c0599fd
--- /dev/null
+++ b/Classes/Client/ExtensionSettingException.php
@@ -0,0 +1,14 @@
+validateExtConf() === false) {
+ throw new ExtensionSettingException(
+ 'Incomplete plesk widget extension settings. See logs for more details',
+ 1736610959
+ );
+ }
+
+ $pleskClient = new Client($this->extConf->getHost(), $this->extConf->getPort());
+ $pleskClient->setCredentials($this->extConf->getUsername(), $this->extConf->getPassword());
+
+ return $pleskClient;
+ }
+
+ private function validateExtConf(): bool
+ {
+ if ($this->extConf->getHost() === '') {
+ $this->logger->error('Plesk host in extension settings can not be empty');
+ return false;
+ }
+
+ if ($this->extConf->getUsername() === '') {
+ $this->logger->error('Plesk user in extension settings can not be empty');
+ return false;
+ }
+
+ if ($this->extConf->getPassword() === '') {
+ $this->logger->error('Plesk password in extension settings can not be empty');
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/Classes/Configuration/ExtConf.php b/Classes/Configuration/ExtConf.php
index b8ed9fe..1c479a9 100644
--- a/Classes/Configuration/ExtConf.php
+++ b/Classes/Configuration/ExtConf.php
@@ -15,34 +15,36 @@
use TYPO3\CMS\Core\Configuration\Exception\ExtensionConfigurationPathDoesNotExistException;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\SingletonInterface;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
/*
* This class streamlines all settings from extension settings
*/
class ExtConf implements SingletonInterface
{
- protected string $diskUsageType = '%';
+ private string $host;
- protected string $host = '';
+ private int $port;
- protected int $port = 8443;
+ private string $username;
- protected string $username = '';
+ private string $password;
- protected string $password = '';
+ private string $diskUsageType;
- public function __construct()
+ private string $domain;
+
+ public function __construct(ExtensionConfiguration $extensionConfiguration)
{
try {
- $extConf = (array)GeneralUtility::makeInstance(ExtensionConfiguration::class)
- ->get('plesk_widget');
+ $extConf = (array)$extensionConfiguration->get('plesk_widget');
- $this->diskUsageType = trim((string)($extConf['diskUsageType'] ?? ''));
$this->host = trim((string)($extConf['host'] ?? ''));
$this->port = (int)($extConf['port'] ?? 8443);
$this->username = trim((string)($extConf['username'] ?? ''));
$this->password = trim((string)($extConf['password'] ?? ''));
+
+ $this->diskUsageType = trim((string)($extConf['diskUsageType'] ?? '%'));
+ $this->domain = trim((string)($extConf['domain'] ?? ''));
} catch (ExtensionConfigurationExtensionNotConfiguredException $extensionConfigurationExtensionNotConfiguredException) {
// Do nothing. The values will still be empty. We catch that as Exception just before the first API call
} catch (ExtensionConfigurationPathDoesNotExistException $extensionConfigurationPathDoesNotExistException) {
@@ -50,11 +52,6 @@ public function __construct()
}
}
- public function getDiskUsageType(): string
- {
- return $this->diskUsageType;
- }
-
public function getHost(): string
{
return $this->host;
@@ -67,13 +64,21 @@ public function getPort(): int
public function getUsername(): string
{
- //return $this->username;
- return '';
+ return $this->username;
}
public function getPassword(): string
{
- //return $this->password;
- return '';
+ return $this->password;
+ }
+
+ public function getDiskUsageType(): string
+ {
+ return $this->diskUsageType;
+ }
+
+ public function getDomain(): string
+ {
+ return $this->domain;
}
}
diff --git a/Classes/DataProvider/PleskDataProvider.php b/Classes/DataProvider/PleskDataProvider.php
deleted file mode 100644
index c1162b2..0000000
--- a/Classes/DataProvider/PleskDataProvider.php
+++ /dev/null
@@ -1,177 +0,0 @@
-extConf = $extConf;
- $this->pleskClient = new Client($this->extConf->getHost(), $this->extConf->getPort());
- $this->pleskClient->setCredentials($this->extConf->getUsername(), $this->extConf->getPassword());
- }
-
- public function getChartData(): array
- {
- return [
- 'labels' => [
- 0 => 'HTTP',
- 1 => 'Database',
- 2 => 'Logs',
- 3 => 'Free'
- ],
- 'datasets' => [
- [
- 'backgroundColor' => WidgetApi::getDefaultChartColors(),
- 'border' => 0,
- 'data' => $this->getWebSpaceStatus()
- ]
- ]
- ];
- }
-
- public function getHosting(): array
- {
- $hostingInfo = $this->pleskClient->site()->getHosting(null, null);
- if ($hostingInfo instanceof HostingInfo) {
- return $hostingInfo->properties;
- }
-
- return [];
- }
-
- public function getCustomer(): GeneralInfo
- {
- $customers = $this->pleskClient->customer()->getAll();
-
- return current($customers);
- }
-
- protected function getWebSpaceStatus(): array
- {
- $diskUsage = $this->getDiskUsage();
- $diskSpace = (int)$this->getLimit('disk_space')->value;
-
- return [
- 0 => $this->calcDiskUsage(
- ($diskUsage->httpdocs + $diskUsage->httpsdocs),
- $diskSpace
- ),
- 1 => $this->calcDiskUsage(
- $diskUsage->dbases,
- $diskSpace
- ),
- 2 => $this->calcDiskUsage(
- $diskUsage->logs,
- $diskSpace
- ),
- 3 => $this->calcDiskUsage(
- ($diskSpace - $diskUsage->httpdocs + $diskUsage->httpsdocs + $diskUsage->dbases + $diskUsage->logs),
- $diskSpace
- )
- ];
- }
-
- protected function calcDiskUsage(int $part, int $total = 0): float
- {
- if ($this->extConf->getDiskUsageType() === '%' && $total !== 0) {
- $value = round(100 / $total * $part, 4);
- } elseif ($this->extConf->getDiskUsageType() === 'MB') {
- $value = round($part / 1024 / 1024, 4);
- } elseif ($this->extConf->getDiskUsageType() === 'GB') {
- $value = round($part / 1024 / 1024 / 1024, 4);
- } else {
- $value = (float)$part;
- }
-
- return $value;
- }
-
- protected function getLimit(string $limit): \StefanFroemken\PleskWidget\Plesk\Webspace\Limit
- {
- return $this->getLimits()->limits[$limit];
- }
-
- public function getLoginLink(): string
- {
- // Get external IP address. Works also within DDEV/Docker containers
- $externalIpAddress = file_get_contents('http://ipecho.net/plain');
-
- if (GeneralUtility::validIP($externalIpAddress)) {
- return sprintf(
- '%s://%s:%d/enterprise/rsession_init.php?PLESKSESSID=%s&success_redirect_url=%s',
- $this->pleskClient->getProtocol() ?: 'https',
- $this->pleskClient->getHost(),
- $this->pleskClient->getPort(),
- $this->pleskClient->server()->createSession($this->extConf->getUsername(), $externalIpAddress),
- '/smb/web/view'
- );
- }
-
- return sprintf(
- '%s://%s:%d',
- $this->pleskClient->getProtocol() ?: 'https',
- $this->pleskClient->getHost(),
- $this->pleskClient->getPort()
- );
- }
-
- public function getLimits(): \StefanFroemken\PleskWidget\Plesk\Webspace\Limits
- {
- $packet = $this->pleskClient->getPacket();
- $getTag = $packet->addChild('webspace')->addChild('get');
- $getTag->addChild('filter');
- $getTag->addChild('dataset')->addChild('limits');
- $response = $this->pleskClient->request($packet, \PleskX\Api\Client::RESPONSE_FULL);
-
- $items = [];
- foreach ($response->xpath('//result') as $xmlResult) {
- $items[] = new Limits($xmlResult->data->limits);
- }
- return $items[0];
- }
-
- public function getSite(): \StefanFroemken\PleskWidget\Plesk\Site
- {
- $packet = $this->pleskClient->getPacket();
- $getTag = $packet->addChild('site')->addChild('get');
- $getTag->addChild('filter');
- $getTag->addChild('dataset')->addChild('gen_info');
- $response = $this->pleskClient->request($packet, \PleskX\Api\Client::RESPONSE_FULL);
-
- $sites = [];
- foreach ($response->xpath('//result') as $xmlResult) {
- $site = new \StefanFroemken\PleskWidget\Plesk\Site($xmlResult);
- $site->genInfo = new \StefanFroemken\PleskWidget\Plesk\Site\GeneralInfo($xmlResult->data->gen_info);
- $sites[] = $site;
- }
- return $sites[0];
- }
-
- public function getDiskUsage(): \PleskX\Api\Struct\Webspace\DiskUsage
- {
- return $this->pleskClient->webspace()->getDiskUsage(null, null);
- }
-}
diff --git a/Classes/DataProvider/ServerDataProvider.php b/Classes/DataProvider/ServerDataProvider.php
new file mode 100644
index 0000000..e1b908c
--- /dev/null
+++ b/Classes/DataProvider/ServerDataProvider.php
@@ -0,0 +1,52 @@
+customer()->getAll();
+
+ return current($customers);
+ }
+
+ public function getLoginLink(Client $pleskClient, string $externalIpAddress): string
+ {
+ if (GeneralUtility::validIP($externalIpAddress)) {
+ // Return direct login link
+ return sprintf(
+ '%s://%s:%d/enterprise/rsession_init.php?PLESKSESSID=%s&success_redirect_url=%s',
+ $pleskClient->getProtocol() ?: 'https',
+ $pleskClient->getHost(),
+ $pleskClient->getPort(),
+ $pleskClient->server()->createSession($this->extConf->getUsername(), $externalIpAddress),
+ '/smb/web/view'
+ );
+ }
+
+ // Return link to login form
+ return sprintf(
+ '%s://%s:%d',
+ $pleskClient->getProtocol() ?: 'https',
+ $pleskClient->getHost(),
+ $pleskClient->getPort()
+ );
+ }
+}
diff --git a/Classes/DataProvider/WebspaceDataProvider.php b/Classes/DataProvider/WebspaceDataProvider.php
new file mode 100644
index 0000000..ce42961
--- /dev/null
+++ b/Classes/DataProvider/WebspaceDataProvider.php
@@ -0,0 +1,118 @@
+pleskClientFactory->create();
+ } catch (ExtensionSettingException $e) {
+ return [];
+ }
+
+ return [
+ 'labels' => [
+ 0 => 'HTTP',
+ 1 => 'Database',
+ 2 => 'Logs',
+ 3 => 'Free',
+ ],
+ 'datasets' => [
+ [
+ 'backgroundColor' => WidgetApi::getDefaultChartColors(),
+ 'border' => 0,
+ 'data' => $this->getWebSpaceStatus($pleskClient),
+ ],
+ ],
+ ];
+ }
+
+ private function getWebSpaceStatus(Client $pleskClient): array
+ {
+ $diskUsage = $this->getDiskUsage($pleskClient);
+ $diskSpace = (int)$this->getLimit('disk_space', $pleskClient)->value;
+
+ return [
+ 0 => $this->calcDiskUsage(
+ ($diskUsage->httpdocs + $diskUsage->httpsdocs),
+ $diskSpace
+ ),
+ 1 => $this->calcDiskUsage(
+ $diskUsage->dbases,
+ $diskSpace
+ ),
+ 2 => $this->calcDiskUsage(
+ $diskUsage->logs,
+ $diskSpace
+ ),
+ 3 => $this->calcDiskUsage(
+ ($diskSpace - $diskUsage->httpdocs + $diskUsage->httpsdocs + $diskUsage->dbases + $diskUsage->logs),
+ $diskSpace
+ ),
+ ];
+ }
+
+ private function calcDiskUsage(int $part, int $total = 0): float
+ {
+ if ($this->extConf->getDiskUsageType() === '%' && $total !== 0) {
+ $value = round(100 / $total * $part, 4);
+ } elseif ($this->extConf->getDiskUsageType() === 'MB') {
+ $value = round($part / 1024 / 1024, 4);
+ } elseif ($this->extConf->getDiskUsageType() === 'GB') {
+ $value = round($part / 1024 / 1024 / 1024, 4);
+ } else {
+ $value = (float)$part;
+ }
+
+ return $value;
+ }
+
+ private function getLimit(string $limit, Client $pleskClient): \StefanFroemken\PleskWidget\Plesk\Webspace\Limit
+ {
+ return $this->getLimits($pleskClient)->limits[$limit];
+ }
+
+ private function getLimits(Client $pleskClient): \StefanFroemken\PleskWidget\Plesk\Webspace\Limits
+ {
+ $packet = $pleskClient->getPacket();
+ $getTag = $packet->addChild('webspace')->addChild('get');
+ $getTag->addChild('filter');
+ $getTag->addChild('dataset')->addChild('limits');
+ $response = $pleskClient->request($packet, Client::RESPONSE_FULL);
+
+ $items = [];
+ foreach ($response->xpath('//result') as $xmlResult) {
+ $items[] = new Limits($xmlResult->data->limits);
+ }
+ return $items[0];
+ }
+
+ private function getDiskUsage(Client $pleskClient): \PleskX\Api\Struct\Webspace\DiskUsage
+ {
+ return $pleskClient->webspace()->getDiskUsage(null, null);
+ }
+}
diff --git a/Classes/Plesk/Hosting.php b/Classes/Plesk/Hosting.php
new file mode 100644
index 0000000..d802a07
--- /dev/null
+++ b/Classes/Plesk/Hosting.php
@@ -0,0 +1,45 @@
+ipAddresses[] = (string)$xmlIpAddress;
+ }
+ foreach ($xmlProperties as $xmlProperty) {
+ $this->properties[(string)$xmlProperty->name] = (string)$xmlProperty->value;
+ }
+ }
+
+ public function getIpAddresses(): array
+ {
+ return $this->ipAddresses;
+ }
+
+ public function getProperties(): array
+ {
+ return $this->properties;
+ }
+}
diff --git a/Classes/Plesk/Site.php b/Classes/Plesk/Site.php
index c30a424..b78cbe7 100644
--- a/Classes/Plesk/Site.php
+++ b/Classes/Plesk/Site.php
@@ -11,26 +11,48 @@
namespace StefanFroemken\PleskWidget\Plesk;
-class Site extends \PleskX\Api\Struct
+use PleskX\Api\Client;
+use PleskX\Api\Struct\Site\GeneralInfo;
+
+class Site
{
- /** @var string */
- public $filterId;
+ private Client $pleskClient;
- /** @var string */
- public $id;
+ private GeneralInfo $generalInformation;
- /** @var string */
- public $status;
+ public function __construct(Client $pleskClient, GeneralInfo $generalInfo)
+ {
+ $this->pleskClient = $pleskClient;
+ $this->generalInformation = $generalInfo;
+ }
- /** @var \StefanFroemken\PleskWidget\Plesk\Site\GeneralInfo */
- public $genInfo;
+ public function getGeneralInformation(): GeneralInfo
+ {
+ return $this->generalInformation;
+ }
- public function __construct($apiResponse)
+ public function getHosting(): ?Hosting
{
- $this->_initScalarProperties($apiResponse, [
- 'filter-id',
- 'id',
- 'status',
+ $response = $this->pleskClient->request([
+ 'site' => [
+ 'get' => [
+ 'filter' => [
+ 'guid' => $this->generalInformation->guid,
+ ],
+ 'dataset' => [
+ 'hosting' => null,
+ ],
+ ],
+ ],
]);
+
+ if (!property_exists($response->data->hosting, 'vrt_hst')) {
+ return null;
+ }
+
+ return new Hosting(
+ $response->data->hosting->vrt_hst->ip_address,
+ $response->data->hosting->vrt_hst->property
+ );
}
}
diff --git a/Classes/Plesk/Site/GeneralInfo.php b/Classes/Plesk/Site/GeneralInfo.php
deleted file mode 100644
index fd7d271..0000000
--- a/Classes/Plesk/Site/GeneralInfo.php
+++ /dev/null
@@ -1,60 +0,0 @@
-_initScalarProperties($apiResponse, [
- 'ascii-name',
- 'cr_date',
- 'description',
- 'guid',
- 'htype',
- 'name',
- 'real_size',
- 'status',
- ]);
-
- foreach ($apiResponse->dns_ip_address as $address) {
- $this->dnsIpAddress[] = $address;
- }
- }
-}
diff --git a/Classes/Service/PleskSiteService.php b/Classes/Service/PleskSiteService.php
new file mode 100644
index 0000000..81cb057
--- /dev/null
+++ b/Classes/Service/PleskSiteService.php
@@ -0,0 +1,52 @@
+cache->has('plesk-widget-sites')) {
+ return $this->cache->get('plesk-widget-sites');
+ }
+
+ $sites = [];
+ foreach ($pleskClient->site()->getAll() as $generalInfo) {
+ $sites[] = new Site($pleskClient, $generalInfo);
+ }
+
+ $this->cache->set('plesk-widget-sites', $sites);
+
+ return $sites;
+ }
+
+ public function getSiteByName(string $name, Client $pleskClient): ?Site
+ {
+ foreach ($this->getSites($pleskClient) as $site) {
+ if ($site->getGeneralInformation()->name === $name) {
+ return $site;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/Classes/Widget/PhpWidget.php b/Classes/Widget/PhpWidget.php
new file mode 100644
index 0000000..f2a7da2
--- /dev/null
+++ b/Classes/Widget/PhpWidget.php
@@ -0,0 +1,73 @@
+request = $request;
+ }
+
+ public function renderWidgetContent(): string
+ {
+ $view = $this->backendViewFactory->create($this->request);
+ $variables = [
+ 'configuration' => $this->configuration,
+ ];
+
+ try {
+ $pleskClient = $this->pleskClientFactory->create();
+
+ if ($this->extConf->getDomain() === '') {
+ $variables['error'] = 'You have to select a domain name in extension settings of EXT:plesk-widget.';
+ } elseif ($site = $this->pleskSiteService->getSiteByName($this->extConf->getDomain(), $pleskClient)) {
+ $variables['domain'] = $this->extConf->getDomain();
+ $variables['hosting'] = $site->getHosting();
+ } else {
+ $variables['error'] = 'Plesk API can not retrieve domain information for ' . $this->extConf->getDomain();
+ }
+ } catch (ExtensionSettingException $extensionSettingException) {
+ $variables['error'] = $extensionSettingException->getMessage();
+ }
+
+ $view->assignMultiple($variables);
+
+ return $view->render('Widget/Php');
+ }
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+}
diff --git a/Classes/Widget/ServerWidget.php b/Classes/Widget/ServerWidget.php
new file mode 100644
index 0000000..66337a8
--- /dev/null
+++ b/Classes/Widget/ServerWidget.php
@@ -0,0 +1,98 @@
+request = $request;
+ }
+
+ public function renderWidgetContent(): string
+ {
+ $view = $this->backendViewFactory->create($this->request);
+ $variables = [
+ 'configuration' => $this->configuration,
+ ];
+
+ try {
+ $pleskClient = $this->pleskClientFactory->create();
+ $externalIpAddress = $this->getExternalIpAddress();
+
+ $variables['customer'] = $this->dataProvider->getCustomer($pleskClient);
+ $variables['externalIpAddress'] = $externalIpAddress;
+ $variables['button'] = $this->getButtonProvider($pleskClient, $externalIpAddress);
+
+ if (
+ $this->extConf->getDomain()
+ && ($site = $this->pleskSiteService->getSiteByName($this->extConf->getDomain(), $pleskClient))
+ && $ipAddresses = $site->getHosting()->getIpAddresses()
+ ) {
+ $variables['ipAddresses'] = $ipAddresses;
+ }
+ } catch (ExtensionSettingException $extensionSettingException) {
+ $variables['error'] = $extensionSettingException->getMessage();
+ }
+
+ $view->assignMultiple($variables);
+
+ return $view->render('Widget/Server');
+ }
+
+ protected function getButtonProvider(Client $pleskClient, string $externalIpAddress): ButtonProvider
+ {
+ return GeneralUtility::makeInstance(
+ ButtonProvider::class,
+ 'Login to Plesk',
+ $this->dataProvider->getLoginLink($pleskClient, $externalIpAddress),
+ '_blank'
+ );
+ }
+
+ private function getExternalIpAddress(): string
+ {
+ // Get external IP address. Works also within DDEV/Docker containers
+ return file_get_contents('http://ipecho.net/plain');
+ }
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+}
diff --git a/Classes/Widget/WebspaceWidget.php b/Classes/Widget/WebspaceWidget.php
new file mode 100644
index 0000000..1c47fe8
--- /dev/null
+++ b/Classes/Widget/WebspaceWidget.php
@@ -0,0 +1,96 @@
+request = $request;
+ }
+
+ public function renderWidgetContent(): string
+ {
+ $view = $this->backendViewFactory->create($this->request);
+
+ $view->assign('configuration', $this->configuration);
+
+ return $view->render('Widget/Webspace');
+ }
+
+ public function getEventData(): array
+ {
+ return [
+ 'graphConfig' => [
+ 'type' => 'doughnut',
+ 'options' => [
+ 'maintainAspectRatio' => false,
+ 'plugins' => [
+ 'legend' => [
+ 'display' => true,
+ 'position' => 'bottom',
+ ],
+ 'title' => [
+ 'display' => true,
+ 'text' => 'Usage in ' . $this->extConf->getDiskUsageType(),
+ ],
+ 'tooltip' => [
+ 'enabled' => true,
+ ],
+ ],
+ 'cutoutPercentage' => 60,
+ ],
+ 'data' => $this->dataProvider->getChartData(),
+ ],
+ ];
+ }
+
+ public function getCssFiles(): array
+ {
+ return [];
+ }
+
+ public function getJavaScriptModuleInstructions(): array
+ {
+ return [
+ JavaScriptModuleInstruction::create('@typo3/dashboard/contrib/chartjs.js'),
+ JavaScriptModuleInstruction::create('@typo3/dashboard/chart-initializer.js'),
+ ];
+ }
+
+ public function getOptions(): array
+ {
+ return $this->options;
+ }
+}
diff --git a/Classes/Widgets/Webspace.php b/Classes/Widgets/Webspace.php
deleted file mode 100644
index cd9a513..0000000
--- a/Classes/Widgets/Webspace.php
+++ /dev/null
@@ -1,134 +0,0 @@
-configuration = $configuration;
- $this->view = $view;
- $this->dataProvider = $dataProvider;
- $this->extConf = $extConf;
- }
-
- public function renderWidgetContent(): string
- {
- try {
- if ($this->extConf->getUsername() === '' || $this->extConf->getPassword() === '') {
- $this->hasError = true;
- $variables = [
- 'error' => 'No username or password given. Please configure authentication in extension settings of EXT:plesk_widget'
- ];
- } else {
- $variables = [
- 'configuration' => $this->configuration,
- 'customer' => $this->dataProvider->getCustomer(),
- 'hosting' => $this->dataProvider->getHosting(),
- 'site' => $this->dataProvider->getSite(),
- 'button' => $this->getButtonProvider()
- ];
- }
- } catch (\Exception $exception) {
- $this->hasError = true;
- $variables = [
- 'error' => $exception->getMessage()
- ];
- }
-
- $this->view->setTemplate('Widget/Webspace');
- $this->view->assign('configuration', $this->configuration);
- $this->view->assignMultiple($variables);
-
- return $this->view->render();
- }
-
- public function getEventData(): array
- {
- if ($this->hasError) {
- $data = '{}';
- } else {
- $data = $this->dataProvider->getChartData();
- }
-
- return [
- 'graphConfig' => [
- 'type' => 'doughnut',
- 'options' => [
- //'maintainAspectRatio' => false,
- 'legend' => [
- 'display' => true,
- 'position' => 'bottom'
- ],
- 'tooltips' => [
- 'enabled' => true
- ],
- 'title' => [
- 'display' => true,
- 'text' => 'Usage in ' . $this->extConf->getDiskUsageType()
- ]
- ],
- 'data' => $data,
- ],
- ];
- }
-
- protected function getButtonProvider(): ButtonProvider
- {
- return GeneralUtility::makeInstance(
- ButtonProvider::class,
- 'Login to Plesk',
- $this->dataProvider->getLoginLink(),
- '_blank'
- );
- }
-
- public function getCssFiles(): array
- {
- return [
- 'EXT:dashboard/Resources/Public/Css/Contrib/chart.css'
- ];
- }
-
- public function getRequireJsModules(): array
- {
- return [
- 'TYPO3/CMS/Dashboard/Contrib/chartjs',
- 'TYPO3/CMS/Dashboard/ChartInitializer',
- ];
- }
-}
diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml
index 0d7a146..848e1ec 100644
--- a/Configuration/Services.yaml
+++ b/Configuration/Services.yaml
@@ -6,12 +6,12 @@ services:
StefanFroemken\PleskWidget\:
resource: '../Classes/*'
+ exclude: '../Classes/Widget/*'
dashboard.widget.plesk.webspace:
- class: 'StefanFroemken\PleskWidget\Widgets\Webspace'
+ class: 'StefanFroemken\PleskWidget\Widget\WebspaceWidget'
arguments:
- $view: '@dashboard.views.widget'
- $dataProvider: '@StefanFroemken\PleskWidget\DataProvider\PleskDataProvider'
+ $dataProvider: '@StefanFroemken\PleskWidget\DataProvider\WebspaceDataProvider'
tags:
- name: dashboard.widget
identifier: 'plesk.webspace'
@@ -20,4 +20,31 @@ services:
description: 'Show used and available diskspace'
iconIdentifier: 'content-widget-rss'
height: 'medium'
- width: 'medium'
+
+ dashboard.widget.plesk.server:
+ class: 'StefanFroemken\PleskWidget\Widget\ServerWidget'
+ arguments:
+ $dataProvider: '@StefanFroemken\PleskWidget\DataProvider\ServerDataProvider'
+ tags:
+ - name: dashboard.widget
+ identifier: 'plesk.server'
+ groupNames: 'systemInfo'
+ title: 'Plesk Server Information'
+ description: 'Show server related information and login link'
+ iconIdentifier: 'content-widget-rss'
+ height: 'medium'
+
+ dashboard.widget.plesk.php:
+ class: 'StefanFroemken\PleskWidget\Widget\PhpWidget'
+ tags:
+ - name: dashboard.widget
+ identifier: 'plesk.php'
+ groupNames: 'systemInfo'
+ title: 'Plesk PHP Settings'
+ description: 'Show PHP related information'
+ iconIdentifier: 'content-widget-rss'
+ height: 'medium'
+
+ StefanFroemken\PleskWidget\Service\PleskSiteService:
+ arguments:
+ $cache: '@cache.runtime'
diff --git a/Configuration/page.tsconfig b/Configuration/page.tsconfig
new file mode 100644
index 0000000..3ba23c1
--- /dev/null
+++ b/Configuration/page.tsconfig
@@ -0,0 +1 @@
+templates.typo3/cms-dashboard.1736608068 = stefanfroemken/plesk-widget:Resources/Private
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Client.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Client.php
index 80e83be..7fb24d9 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Client.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Client.php
@@ -1,5 +1,11 @@
_version;
$content = "";
- $content .= '';
+ $content .= '';
return new SimpleXMLElement($content);
}
@@ -163,9 +167,9 @@ public function request($request, $mode = self::RESPONSE_SHORT)
}
}
- if ('sdk' == $this->_protocol) {
- $version = ('' == $this->_version) ? null : $this->_version;
- $requestXml = new SimpleXMLElement((string) $request);
+ if ($this->_protocol == 'sdk') {
+ $version = ($this->_version == '') ? null : $this->_version;
+ $requestXml = new SimpleXMLElement((string)$request);
$xml = \pm_ApiRpc::getService($version)->call($requestXml->children()[0]->asXml(), $this->_login);
} else {
$xml = $this->_performHttpRequest($request);
@@ -175,7 +179,7 @@ public function request($request, $mode = self::RESPONSE_SHORT)
? call_user_func($this->_verifyResponseCallback, $xml)
: $this->_verifyResponse($xml);
- return (self::RESPONSE_FULL == $mode) ? $xml : $xml->xpath('//result')[0];
+ return ($mode == self::RESPONSE_FULL) ? $xml : $xml->xpath('//result')[0];
}
/**
@@ -199,13 +203,13 @@ private function _performHttpRequest($request)
curl_setopt($curl, CURLOPT_HTTPHEADER, $this->_getHeaders());
curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
- if ('' !== $this->_proxy) {
+ if ($this->_proxy !== '') {
curl_setopt($curl, CURLOPT_PROXY, $this->_proxy);
}
$result = curl_exec($curl);
- if (false === $result) {
+ if ($result === false) {
throw new Client\Exception(curl_error($curl), curl_errno($curl));
}
@@ -219,7 +223,6 @@ private function _performHttpRequest($request)
/**
* Perform multiple API requests using single HTTP request.
*
- * @param $requests
* @param int $mode
*
* @throws Client\Exception
@@ -233,21 +236,20 @@ public function multiRequest($requests, $mode = self::RESPONSE_SHORT)
foreach ($requests as $request) {
if ($request instanceof SimpleXMLElement) {
throw new Client\Exception('SimpleXML type of request is not supported for multi requests.');
- } else {
- if (is_array($request)) {
- $request = $this->_arrayToXml($request, $requestXml)->asXML();
- } elseif (preg_match('/^[a-z]/', $request)) {
- $this->_expandRequestShortSyntax($request, $requestXml);
- }
}
+ if (is_array($request)) {
+ $request = $this->_arrayToXml($request, $requestXml)->asXML();
+ } elseif (preg_match('/^[a-z]/', $request)) {
+ $this->_expandRequestShortSyntax($request, $requestXml);
+ }
+
$responses[] = $this->request($request);
}
- if ('sdk' == $this->_protocol) {
+ if ($this->_protocol == 'sdk') {
throw new Client\Exception('Multi requests are not supported via SDK.');
- } else {
- $responseXml = $this->_performHttpRequest($requestXml->asXML());
}
+ $responseXml = $this->_performHttpRequest($requestXml->asXML());
$responses = [];
foreach ($responseXml->children() as $childNode) {
@@ -259,7 +261,7 @@ public function multiRequest($requests, $mode = self::RESPONSE_SHORT)
$dom->documentElement->appendChild($childDomNode);
$response = simplexml_load_string($dom->saveXML());
- $responses[] = (self::RESPONSE_FULL == $mode) ? $response : $response->xpath('//result')[0];
+ $responses[] = ($mode == self::RESPONSE_FULL) ? $response : $response->xpath('//result')[0];
}
return $responses;
@@ -296,13 +298,13 @@ protected function _getHeaders()
*/
protected function _verifyResponse($xml)
{
- if ($xml->system && $xml->system->status && 'error' == (string) $xml->system->status) {
- throw new Exception((string) $xml->system->errtext, (int) $xml->system->errcode);
+ if ($xml->system && $xml->system->status && (string)$xml->system->status == 'error') {
+ throw new Exception((string)$xml->system->errtext, (int)$xml->system->errcode);
}
if ($xml->xpath('//status[text()="error"]') && $xml->xpath('//errcode') && $xml->xpath('//errtext')) {
- $errorCode = (int) $xml->xpath('//errcode')[0];
- $errorMessage = (string) $xml->xpath('//errtext')[0];
+ $errorCode = (int)$xml->xpath('//errcode')[0];
+ $errorMessage = (string)$xml->xpath('//errtext')[0];
throw new Exception($errorMessage, $errorCode);
}
@@ -312,7 +314,6 @@ protected function _verifyResponse($xml)
* Expand short syntax (some.method.call) into full XML representation.
*
* @param string $request
- * @param SimpleXMLElement $xml
*
* @return string
*/
@@ -327,7 +328,7 @@ protected function _expandRequestShortSyntax($request, SimpleXMLElement $xml)
if ($part !== $lastParts) {
$node = $node->addChild($name);
} else {
- $node->{$name} = (string) $value;
+ $node->{$name} = (string)$value;
}
}
@@ -337,8 +338,6 @@ protected function _expandRequestShortSyntax($request, SimpleXMLElement $xml)
/**
* Convert array to XML representation.
*
- * @param array $array
- * @param SimpleXMLElement $xml
* @param string $parentEl
*
* @return SimpleXMLElement
@@ -350,7 +349,7 @@ protected function _arrayToXml(array $array, SimpleXMLElement $xml, $parentEl =
if (is_array($value)) {
$this->_arrayToXml($value, $this->_isAssocArray($value) ? $xml->addChild($el) : $xml, $el);
} else {
- $xml->{$el} = (string) $value;
+ $xml->{$el} = (string)$value;
}
}
@@ -358,8 +357,6 @@ protected function _arrayToXml(array $array, SimpleXMLElement $xml, $parentEl =
}
/**
- * @param array $array
- *
* @return bool
*/
protected function _isAssocArray(array $array)
@@ -375,7 +372,7 @@ protected function _isAssocArray(array $array)
protected function _getOperator($name)
{
if (!isset($this->_operatorsCache[$name])) {
- $className = '\\PleskX\\Api\\Operator\\'.$name;
+ $className = '\\PleskX\\Api\\Operator\\' . $name;
$this->_operatorsCache[$name] = new $className($this);
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Client/Exception.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Client/Exception.php
index 0d26d30..66860c5 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Client/Exception.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Client/Exception.php
@@ -1,11 +1,15 @@
_client = $client;
if (is_null($this->_wrapperTag)) {
- $classNameParts = explode('\\', get_class($this));
+ $classNameParts = explode('\\', static::class);
$this->_wrapperTag = end($classNameParts);
$this->_wrapperTag = strtolower(preg_replace('/([a-z])([A-Z])/', '\1-\2', $this->_wrapperTag));
}
@@ -62,7 +68,7 @@ protected function _delete($field, $value, $deleteMethodName = 'del')
],
]);
- return 'ok' === (string) $response->status;
+ return (string)$response->status === 'ok';
}
/**
@@ -70,9 +76,6 @@ protected function _delete($field, $value, $deleteMethodName = 'del')
* @param string $infoTag
* @param string|null $field
* @param int|string|null $value
- * @param callable|null $filter
- *
- * @return mixed
*/
protected function _getItems($structClass, $infoTag, $field = null, $value = null, callable $filter = null)
{
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Aps.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Aps.php
index 9f4bde3..54f9600 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Aps.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Aps.php
@@ -1,8 +1,12 @@
addChild($this->_wrapperTag)->addChild($command);
foreach ($properties as $name => $value) {
- if (false !== strpos($value, '&')) {
+ if (str_contains($value, '&')) {
$info->$name = $value;
continue;
}
@@ -50,15 +55,13 @@ private function _process($command, array $properties)
}
/**
- * @param array $properties
- *
* @return bool
*/
public function updateUser(array $properties)
{
$response = $this->_process('set-db-user', $properties);
- return 'ok' === (string) $response->status;
+ return (string)$response->status === 'ok';
}
/**
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DatabaseServer.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DatabaseServer.php
index fc338ea..751967b 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DatabaseServer.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DatabaseServer.php
@@ -1,5 +1,11 @@
request('get-supported-types');
- return (array) $response->type;
+ return (array)$response->type;
}
/**
@@ -61,7 +67,7 @@ private function _get($field = null, $value = null)
$items = [];
foreach ($response->xpath('//result') as $xmlResult) {
$item = new Struct\Info($xmlResult->data);
- $item->id = (int) $xmlResult->id;
+ $item->id = (int)$xmlResult->id;
$items[] = $item;
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Dns.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Dns.php
index 30920a7..91ef5ec 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Dns.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Dns.php
@@ -1,5 +1,11 @@
xpath('//result') as $xmlResult) {
$item = new Struct\Info($xmlResult->data);
- $item->id = (int) $xmlResult->id;
+ $item->id = (int)$xmlResult->id;
$items[] = $item;
}
@@ -106,7 +111,6 @@ public function delete($field, $value)
/**
* Delete multiply records by one request.
*
- * @param array $recordIds
*
* @return \PleskX\Api\XmlResponse[]
*/
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DnsTemplate.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DnsTemplate.php
index 18e6634..40391af 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DnsTemplate.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/DnsTemplate.php
@@ -1,5 +1,11 @@
xpath('//result') as $xmlResult) {
$item = new Struct\Info($xmlResult->data);
- $item->id = (int) $xmlResult->id;
+ $item->id = (int)$xmlResult->id;
$items[] = $item;
}
@@ -83,6 +87,6 @@ public function delete($field, $value)
$response = $this->_client->request($packet);
- return 'ok' === (string) $response->status;
+ return (string)$response->status === 'ok';
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/EventLog.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/EventLog.php
index 6b7325a..210f442 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/EventLog.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/EventLog.php
@@ -1,5 +1,11 @@
request('get-last-id')->getValue('id');
+ return (int)$this->request('get-last-id')->getValue('id');
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ip.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ip.php
index 4bc87f7..91550c0 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ip.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ip.php
@@ -1,5 +1,11 @@
_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL);
foreach ($response->locale->get->result as $localeInfo) {
- $locales[(string) $localeInfo->info->id] = new Struct\Info($localeInfo->info);
+ $locales[(string)$localeInfo->info->id] = new Struct\Info($localeInfo->info);
}
return !is_null($id) ? reset($locales) : $locales;
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/LogRotation.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/LogRotation.php
index ef0b60e..e745205 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/LogRotation.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/LogRotation.php
@@ -1,8 +1,12 @@
{$field} = $value;
$response = $this->_client->request($packet);
- return 'ok' === (string) $response->status;
+ return (string)$response->status === 'ok';
}
/**
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/PhpHandler.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/PhpHandler.php
index 66f1ec1..7ab15ed 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/PhpHandler.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/PhpHandler.php
@@ -1,5 +1,11 @@
xpath('//result') as $xmlResult) {
$item = new Struct\GeneralInfo($xmlResult->data);
- $item->id = (int) $xmlResult->id;
+ $item->id = (int)$xmlResult->id;
$items[] = $item;
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ResellerPlan.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ResellerPlan.php
index 17d533f..b79f591 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ResellerPlan.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ResellerPlan.php
@@ -1,8 +1,12 @@
_client->getPacket();
$createTag = $packet->addChild($this->_wrapperTag)->addChild('create');
- if ('' !== $ipAddress) {
+ if ($ipAddress !== '') {
$createTag->addChild('ip_address', $ipAddress);
}
- if ('' !== $description) {
+ if ($description !== '') {
$createTag->addChild('description', $description);
}
$response = $this->_client->request($packet);
- return (string) $response->key;
+ return (string)$response->key;
}
/**
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Server.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Server.php
index 65cbae6..420a951 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Server.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Server.php
@@ -1,5 +1,11 @@
addChild($this->_wrapperTag)->addChild('get_protos');
$response = $this->_client->request($packet);
- return (array) $response->protos->proto;
+ return (array)$response->protos->proto;
}
public function getGeneralInfo()
@@ -43,7 +49,7 @@ public function getKeyInfo()
$keyInfoXml = $this->_getInfo('key');
foreach ($keyInfoXml->property as $property) {
- $keyInfo[(string) $property->name] = (string) $property->value;
+ $keyInfo[(string)$property->name] = (string)$property->value;
}
return $keyInfo;
@@ -58,7 +64,7 @@ public function getComponents()
$componentsXml = $this->_getInfo('components');
foreach ($componentsXml->component as $component) {
- $components[(string) $component->name] = (string) $component->version;
+ $components[(string)$component->name] = (string)$component->version;
}
return $components;
@@ -73,10 +79,10 @@ public function getServiceStates()
$statesXml = $this->_getInfo('services_state');
foreach ($statesXml->srv as $service) {
- $states[(string) $service->id] = [
- 'id' => (string) $service->id,
- 'title' => (string) $service->title,
- 'state' => (string) $service->state,
+ $states[(string)$service->id] = [
+ 'id' => (string)$service->id,
+ 'title' => (string)$service->title,
+ 'state' => (string)$service->state,
];
}
@@ -97,7 +103,7 @@ public function getShells()
$shellsXml = $this->_getInfo('shells');
foreach ($shellsXml->shell as $shell) {
- $shells[(string) $shell->name] = (string) $shell->path;
+ $shells[(string)$shell->name] = (string)$shell->path;
}
return $shells;
@@ -110,7 +116,7 @@ public function getNetworkInterfaces()
{
$interfacesXml = $this->_getInfo('interfaces');
- return (array) $interfacesXml->interface;
+ return (array)$interfacesXml->interface;
}
public function getStatistics()
@@ -127,7 +133,7 @@ public function getSiteIsolationConfig()
$configXml = $this->_getInfo('site-isolation-config');
foreach ($configXml->property as $property) {
- $config[(string) $property->name] = (string) $property->value;
+ $config[(string)$property->name] = (string)$property->value;
}
return $config;
@@ -154,7 +160,7 @@ public function createSession($login, $clientIp)
$dataNode->addChild('source_server');
$response = $this->_client->request($packet);
- return (string) $response->id;
+ return (string)$response->id;
}
/**
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ServicePlan.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ServicePlan.php
index 41fa075..e440693 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ServicePlan.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/ServicePlan.php
@@ -1,5 +1,11 @@
request('get');
foreach ($response->session as $sessionInfo) {
- $sessions[(string) $sessionInfo->id] = new Struct\Info($sessionInfo);
+ $sessions[(string)$sessionInfo->id] = new Struct\Info($sessionInfo);
}
return $sessions;
@@ -31,6 +37,6 @@ public function terminate($sessionId)
{
$response = $this->request("terminate.session-id=$sessionId");
- return 'ok' === (string) $response->status;
+ return (string)$response->status === 'ok';
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Site.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Site.php
index f92eae6..8949793 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Site.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Site.php
@@ -1,5 +1,11 @@
data);
- $item->id = (int) $xmlResult->id;
+ $item->id = (int)$xmlResult->id;
$items[] = $item;
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ui.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ui.php
index 187fcd2..01bab45 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ui.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/Ui.php
@@ -1,5 +1,11 @@
_client->request($packet);
- return (int) $response->id;
+ return (int)$response->id;
}
/**
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/VirtualDirectory.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/VirtualDirectory.php
index 1c2ae8b..79ed025 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/VirtualDirectory.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Operator/VirtualDirectory.php
@@ -1,5 +1,11 @@
getDocComment();
$propertyType = preg_replace('/^.+ @var ([a-z]+) .+$/', '\1', $docBlock);
- if ('string' == $propertyType) {
- $value = (string) $value;
- } elseif ('int' == $propertyType) {
- $value = (int) $value;
- } elseif ('bool' == $propertyType) {
- $value = in_array((string) $value, ['true', 'on', 'enabled']);
+ if ($propertyType == 'string') {
+ $value = (string)$value;
+ } elseif ($propertyType == 'int') {
+ $value = (int)$value;
+ } elseif ($propertyType == 'bool') {
+ $value = in_array((string)$value, ['true', 'on', 'enabled']);
} else {
throw new \Exception("Unknown property type '$propertyType'.");
}
@@ -56,7 +61,7 @@ protected function _initScalarProperties($apiResponse, array $properties)
*/
private function _underToCamel($under)
{
- $under = '_'.str_replace('_', ' ', strtolower($under));
+ $under = '_' . str_replace('_', ' ', strtolower($under));
return ltrim(str_replace(' ', '', ucwords($under)), '_');
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Certificate/Info.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Certificate/Info.php
index 7689bcb..129ac11 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Certificate/Info.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Certificate/Info.php
@@ -1,5 +1,11 @@
permissions = [];
foreach ($apiResponse->permissions->permission as $permissionInfo) {
- $this->permissions[(string) $permissionInfo->name] = (string) $permissionInfo->value;
+ $this->permissions[(string)$permissionInfo->name] = (string)$permissionInfo->value;
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Reseller/Info.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Reseller/Info.php
index a1b6bf8..2df7d10 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Reseller/Info.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Reseller/Info.php
@@ -1,5 +1,11 @@
diskSpace = [];
foreach ($apiResponse->diskspace as $disk) {
- $this->diskSpace[(string) $disk->device->name] = new Statistics\DiskSpace($disk->device);
+ $this->diskSpace[(string)$disk->device->name] = new Statistics\DiskSpace($disk->device);
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Server/Statistics/DiskSpace.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Server/Statistics/DiskSpace.php
index 1f21655..ae964b8 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Server/Statistics/DiskSpace.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Server/Statistics/DiskSpace.php
@@ -1,5 +1,11 @@
vrt_hst->property as $property) {
- $this->properties[(string) $property->name] = (string) $property->value;
+ $this->properties[(string)$property->name] = (string)$property->value;
}
$this->_initScalarProperties($apiResponse->vrt_hst, [
'ip_address',
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Site/Info.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Site/Info.php
index ea69dd9..df17f1f 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Site/Info.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Site/Info.php
@@ -1,5 +1,11 @@
property as $propertyInfo) {
- $this->properties[(string) $propertyInfo->name] = (string) $propertyInfo->value;
+ $this->properties[(string)$propertyInfo->name] = (string)$propertyInfo->value;
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Ui/CustomButton.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Ui/CustomButton.php
index ed7a712..417951a 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Ui/CustomButton.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Ui/CustomButton.php
@@ -1,5 +1,11 @@
dns_ip_address as $ip) {
- $this->ipAddresses[] = (string) $ip;
+ $this->ipAddresses[] = (string)$ip;
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/HostingPropertyInfo.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/HostingPropertyInfo.php
index 7922d18..d5024a9 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/HostingPropertyInfo.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/HostingPropertyInfo.php
@@ -1,5 +1,11 @@
limits = [];
foreach ($apiResponse->descriptor->property as $propertyInfo) {
- $this->limits[(string) $propertyInfo->name] = new LimitInfo($propertyInfo);
+ $this->limits[(string)$propertyInfo->name] = new LimitInfo($propertyInfo);
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/LimitInfo.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/LimitInfo.php
index b8af3b6..2cb0614 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/LimitInfo.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/LimitInfo.php
@@ -1,5 +1,11 @@
limits = [];
foreach ($apiResponse->limit as $limit) {
- $this->limits[(string) $limit->name] = new Limit($limit);
+ $this->limits[(string)$limit->name] = new Limit($limit);
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionDescriptor.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionDescriptor.php
index bc333ba..106611a 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionDescriptor.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionDescriptor.php
@@ -1,5 +1,11 @@
permissions = [];
foreach ($apiResponse->descriptor->property as $propertyInfo) {
- $this->permissions[(string) $propertyInfo->name] = new PermissionInfo($propertyInfo);
+ $this->permissions[(string)$propertyInfo->name] = new PermissionInfo($propertyInfo);
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionInfo.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionInfo.php
index 9414a31..34b66b5 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionInfo.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PermissionInfo.php
@@ -1,5 +1,11 @@
properties = [];
foreach ($apiResponse->webspace->get->result->data->{'php-settings'}->setting as $setting) {
- $this->properties[(string) $setting->name] = (string) $setting->value;
+ $this->properties[(string)$setting->name] = (string)$setting->value;
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php
index 1aff2f7..e9b0af9 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php
@@ -1,5 +1,11 @@
properties = [];
foreach ($apiResponse->descriptor->property as $propertyInfo) {
- $this->properties[(string) $propertyInfo->name] = new HostingPropertyInfo($propertyInfo);
+ $this->properties[(string)$propertyInfo->name] = new HostingPropertyInfo($propertyInfo);
}
}
}
diff --git a/Resources/Private/Php/plesk/api-php-lib/src/Api/XmlResponse.php b/Resources/Private/Php/plesk/api-php-lib/src/Api/XmlResponse.php
index 687b6d8..34f7560 100644
--- a/Resources/Private/Php/plesk/api-php-lib/src/Api/XmlResponse.php
+++ b/Resources/Private/Php/plesk/api-php-lib/src/Api/XmlResponse.php
@@ -1,5 +1,11 @@
xpath('//'.$node)[0];
+ return (string)$this->xpath('//' . $node)[0];
}
}
diff --git a/Resources/Private/Templates/Dashboard/Widget/Webspace.html b/Resources/Private/Templates/Dashboard/Widget/Webspace.html
deleted file mode 100644
index 9681b75..0000000
--- a/Resources/Private/Templates/Dashboard/Widget/Webspace.html
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
- {error}
-
-
-
-
-
- - Owner
- - {customer.personalName}
-
-
- - IP Address
-
- - {ipAddress}
-
-
-
- - Hosting
- - PHP Handler: {hosting.php_handler_id}
- - PHP memory: {hosting.memory_limit}
- - PHP exec. time: {hosting.max_execution_time}
- - PHP max. upload: {hosting.upload_max_filesize}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Resources/Private/Templates/Widget/Php.html b/Resources/Private/Templates/Widget/Php.html
new file mode 100644
index 0000000..246d120
--- /dev/null
+++ b/Resources/Private/Templates/Widget/Php.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+ {error}
+
+ {domain}
+
+ - max_execution_time
+ - {hosting.properties.max_execution_time}
+
+
+ - open_basedir
+ - {hosting.properties.open_basedir}
+
+
+ - memory_limit
+ - {hosting.properties.memory_limit}
+
+
+ - post_max_size
+ - {hosting.properties.post_max_size}
+
+
+ - upload_max_filesize
+ - {hosting.properties.upload_max_filesize}
+
+
+
+
+
+
+
+
+
diff --git a/Resources/Private/Templates/Widget/Server.html b/Resources/Private/Templates/Widget/Server.html
new file mode 100644
index 0000000..ec78e5d
--- /dev/null
+++ b/Resources/Private/Templates/Widget/Server.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ {error}
+
+
+ - Owner
+ - {customer.personalName}
+
+
+ - Server IP Address
+
+ - {ipAddress}
+
+
+
+ Public IP Address
+ {externalIpAddress}
+
+
+
+
+
+
+
+
+
diff --git a/Resources/Private/Templates/Widget/Webspace.html b/Resources/Private/Templates/Widget/Webspace.html
new file mode 100644
index 0000000..043c825
--- /dev/null
+++ b/Resources/Private/Templates/Widget/Webspace.html
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ {error}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/composer.json b/composer.json
index c06da0a..871ee1c 100644
--- a/composer.json
+++ b/composer.json
@@ -18,13 +18,19 @@
"source": "https://github.com/froemken/plesk_widget"
},
"require": {
- "php": "^7.4 || ^8.0",
- "typo3/cms-core": "^11.5.41 || ^12.4.24",
- "typo3/cms-dashboard": "^11.5.41 || ^12.4.24",
+ "typo3/cms-core": "^12.4.24",
+ "typo3/cms-dashboard": "^12.4.24",
"plesk/api-php-lib": "1.1.2"
},
"require-dev": {
- "friendsofphp/php-cs-fixer": "^3.4"
+ "friendsofphp/php-cs-fixer": "^3.14",
+ "phpunit/phpunit": "^9.6",
+ "roave/security-advisories": "dev-latest",
+ "typo3/coding-standards": "^0.6",
+ "typo3/testing-framework": "^7.0.2"
+ },
+ "replace": {
+ "typo3-ter/plesk-widget": "self.version"
},
"autoload": {
"psr-4": {
@@ -33,25 +39,19 @@
}
},
"config": {
- "vendor-dir": ".build/vendor"
+ "sort-packages": true,
+ "vendor-dir": ".Build/vendor",
+ "bin-dir": ".Build/bin",
+ "allow-plugins": {
+ "typo3/class-alias-loader": true,
+ "typo3/cms-composer-installers": true
+ }
},
"extra": {
"typo3/cms": {
"extension-key": "plesk_widget",
- "app-dir": ".build",
- "web-dir": ".build/public"
+ "app-dir": ".Build",
+ "web-dir": ".Build/public"
}
- },
- "scripts": {
- "php:fix": ".build/vendor/bin/php-cs-fixer --config=Build/.php_cs.php fix Classes",
- "ci:php:lint": "find *.php Classes Configuration -name '*.php' -print0 | xargs -0 -n 1 -P 4 php -l",
- "ci:php:fixer": ".build/vendor/bin/php-cs-fixer --config=Build/.php_cs.php fix --dry-run -v --show-progress=dots --diff Classes",
- "link-extension": [
- "@php -r 'is_dir($extFolder=__DIR__.\"/.build/public/typo3conf/ext/\") || mkdir($extFolder, 0777, true);'",
- "@php -r 'file_exists($extFolder=__DIR__.\"/.build/public/typo3conf/ext/plesk_widget\") || symlink(__DIR__,$extFolder);'"
- ],
- "post-autoload-dump": [
- "@link-extension"
- ]
}
}
diff --git a/ext_conf_template.txt b/ext_conf_template.txt
index f67fe05..05676b5 100644
--- a/ext_conf_template.txt
+++ b/ext_conf_template.txt
@@ -1,10 +1,12 @@
-# cat=basic; type=options[Percent (%)=%,MegaByte (MB)=MB,GigaByte (GB)=GB]; label=Disk usage type: Show disk usage in percent or in Mega- or GigaByte?
-diskUsageType = %
-# cat=basic; type=string; label=Plesk host: Insert without scheme, port or path
+# cat=plesk; type=string; label=Plesk host: Insert without scheme, port or path
host =
-# cat=basic; type=int; label=Plesk port: Plesk default port is 8443
+# cat=plesk; type=int; label=Plesk port: Plesk default port is 8443
port = 8443
-# cat=basic; type=string; label=Plesk username
+# cat=plesk; type=string; label=Plesk username
username =
-# cat=basic; type=string; label=Plesk password
+# cat=plesk; type=string; label=Plesk password
password =
+# cat=basic; type=options[Percent (%)=%,MegaByte (MB)=MB,GigaByte (GB)=GB]; label=Disk usage type: Show disk usage in percent or in Mega- or GigaByte?
+diskUsageType = %
+# cat=basic; type=string; label=Domain: Enter domain name to show info about. Without www and without scheme (https://)
+domain =
diff --git a/ext_emconf.php b/ext_emconf.php
index c9e3490..d1a3757 100644
--- a/ext_emconf.php
+++ b/ext_emconf.php
@@ -1,5 +1,12 @@
'Plesk Widget',
'description' => 'Shows information about your plesk based customer control center',
@@ -9,11 +16,11 @@
'author_company' => '',
'state' => 'stable',
'clearCacheOnLoad' => 0,
- 'version' => '1.2.1',
+ 'version' => '2.0.0',
'constraints' => [
'depends' => [
- 'typo3' => '11.5.41-12.4.99',
- 'dashboard' => '11.5.41-12.4.99',
+ 'typo3' => '12.4.24',
+ 'dashboard' => '12.4.24',
],
'conflicts' => [
],