diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..dd34ec4e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +version: 2 +updates: + - package-ecosystem: "composer" + directory: "/" + schedule: + interval: "weekly" + commit-message: + prefix: "TECH " diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..cf9bb311 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,13 @@ +name: test + +on: [push] + +jobs: + test: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - run: docker compose run tests + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 17c52938..3efa5ae6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -/php/tests/node_modules -/vendor +/.env +/vendor/ /phpunit.xml +/.phpunit.result.cache +/coverage.xml diff --git a/Dockerfile b/Dockerfile index 2d127c45..d163d3f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,9 @@ -FROM php:5.6-cli +FROM php:8.2-cli -RUN mkdir /opt/api-php-lib -RUN docker-php-ext-install pcntl \ +RUN apt-get update \ + && apt-get install -y unzip \ + && docker-php-ext-install pcntl \ + && pecl install xdebug \ + && echo "zend_extension=xdebug.so" > /usr/local/etc/php/conf.d/xdebug.ini \ + && echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/xdebug.ini \ && curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index f4ec4e3d..00000000 --- a/Gruntfile.js +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 1999-2016. Parallels IP Holdings GmbH. - -module.exports = function(grunt) { - grunt.initConfig({ - phpunit: { - classes: {}, - options: {} - }, - watch: { - test: { - files: ['tests/*Test.php', 'src/**/*.*'], - tasks: ['phpunit'] - } - } - }); - - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-phpunit'); - grunt.registerTask('default', ['phpunit']); -}; diff --git a/LICENSE b/LICENSE index 368e39a8..3d85e2f9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 1999-2016. Parallels IP Holdings GmbH. +Copyright 1999-2025. WebPros International GmbH. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index a45784e0..25fa379a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ ## PHP library for Plesk XML-RPC API +[![Test Status](https://github.com/plesk/api-php-lib/actions/workflows/test.yml/badge.svg)](https://github.com/plesk/api-php-lib/actions/workflows/test.yml) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/plesk/api-php-lib/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/plesk/api-php-lib/?branch=master) +[![codecov](https://codecov.io/gh/plesk/api-php-lib/branch/master/graph/badge.svg?token=5Kwbddpdeb)](https://codecov.io/gh/plesk/api-php-lib) PHP object-oriented library for Plesk XML-RPC API. @@ -8,7 +10,7 @@ PHP object-oriented library for Plesk XML-RPC API. [Composer](https://getcomposer.org/) is a preferable way to install the library: -`composer require plesk/api-php-lib:@dev` +`composer require plesk/api-php-lib` ## Usage Examples @@ -48,14 +50,18 @@ One the possible ways to become familiar with the library is to check the unit t To run the unit tests use the following command: -`REMOTE_HOST=your-plesk-host.dom REMOTE_PASSWORD=password ./vendor/bin/phpunit` +`REMOTE_HOST=your-plesk-host.dom REMOTE_PASSWORD=password composer test` To use custom port one can provide a URL (e.g. for Docker container): -`REMOTE_URL=https://your-plesk-host.dom:port REMOTE_PASSWORD=password ./vendor/bin/phpunit` +`REMOTE_URL=https://your-plesk-host.dom:port REMOTE_PASSWORD=password composer test` -## Using Grunt for Continuous Testing +One more way to run tests is to use Docker: -* Install Node.js -* Install dependencies via `npm install` command -* Run `REMOTE_HOST=your-plesk-host.dom REMOTE_PASSWORD=password grunt watch:test` +`docker-compose run tests` + +## Continuous Testing + +During active development it could be more convenient to run tests in continuous manner. Here is the way how to achieve it: + +`REMOTE_URL=https://your-plesk-host.dom:port REMOTE_PASSWORD=password composer test:watch` diff --git a/composer.json b/composer.json index c651082e..0c34a4ff 100644 --- a/composer.json +++ b/composer.json @@ -1,37 +1,58 @@ { "name": "plesk/api-php-lib", + "type": "library", "description": "PHP object-oriented library for Plesk XML-RPC API", "license": "Apache-2.0", "authors": [ { "name": "Alexei Yuzhakov", "email": "sibprogrammer@gmail.com" + }, + { + "name": "WebPros International GmbH.", + "email": "plesk-dev-leads@plesk.com" } ], - "minimum-stability": "dev", "require": { - "php": ">=5.6.0" + "php": "^7.4 || ^8.0", + "ext-curl": "*", + "ext-xml": "*", + "ext-simplexml": "*", + "ext-dom": "*" }, "require-dev": { - "phpunit/phpunit": "5.7.*", - "phpunit/php-invoker": "*", - "phpunit/dbunit": ">=1.2", - "sebastian/environment": "^2.0" + "phpunit/phpunit": "^9", + "spatie/phpunit-watcher": "^1.22", + "vimeo/psalm": "^4.10 || ^5.0", + "squizlabs/php_codesniffer": "^3.6 || ^4.0" }, "config": { - "process-timeout": 0 + "process-timeout": 0, + "platform": { + "php": "7.4.27" + } }, "scripts": { - "test": "phpunit" + "test": "phpunit", + "test:watch": "phpunit-watcher watch", + "lint": [ + "psalm", + "phpcs" + ] }, "autoload": { "psr-4": { - "PleskX\\": "src/PleskX/" + "PleskX\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "PleskXTest\\": "tests/" } }, "extra": { "branch-alias": { - "dev-master": "0.1.x-dev" + "dev-master": "2.0.x-dev" } } } diff --git a/composer.lock b/composer.lock index c3feeca5..a1a80227 100644 --- a/composer.lock +++ b/composer.lock @@ -1,46 +1,51 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "fbc1f466b0f53331ec17c695470701dd", - "content-hash": "ba2fb56608e462276a5906cda2aa30cb", + "content-hash": "fb3292e22b0e205555a79dcfa16c74ea", "packages": [], "packages-dev": [ { - "name": "doctrine/instantiator", - "version": "dev-master", + "name": "amphp/amp", + "version": "v2.6.4", "source": { "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5" + "url": "https://github.com/amphp/amp.git", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5", - "reference": "5acd2bd8c2b600ad5cc4c9180ebf0a930604d6a5", + "url": "https://api.github.com/repos/amphp/amp/zipball/ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", + "reference": "ded3d9be08f526089eb7ee8d9f16a9768f9dec2d", "shasum": "" }, "require": { - "php": ">=5.3,<8.0-DEV" + "php": ">=7.1" }, "require-dev": { - "athletic/athletic": "~0.1.8", - "ext-pdo": "*", - "ext-phar": "*", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~2.0" + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1", + "ext-json": "*", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^7 | ^8 | ^9", + "react/promise": "^2", + "vimeo/psalm": "^3.12" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { + "files": [ + "lib/functions.php", + "lib/Internal/functions.php" + ], "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + "Amp\\": "lib" } }, "notification-url": "https://packagist.org/downloads/", @@ -49,92 +54,152 @@ ], "authors": [ { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "http://ocramius.github.com/" + "name": "Daniel Lowrey", + "email": "rdlowrey@php.net" + }, + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Bob Weinand", + "email": "bobwei9@hotmail.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" } ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://github.com/doctrine/instantiator", + "description": "A non-blocking concurrency framework for PHP applications.", + "homepage": "https://amphp.org/amp", "keywords": [ - "constructor", - "instantiate" + "async", + "asynchronous", + "awaitable", + "concurrency", + "event", + "event-loop", + "future", + "non-blocking", + "promise" + ], + "support": { + "irc": "irc://irc.freenode.org/amphp", + "issues": "https://github.com/amphp/amp/issues", + "source": "https://github.com/amphp/amp/tree/v2.6.4" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } ], - "time": "2017-02-16 16:15:51" + "time": "2024-03-21T18:52:26+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.x-dev", + "name": "amphp/byte-stream", + "version": "v1.8.2", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + "url": "https://github.com/amphp/byte-stream.git", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "url": "https://api.github.com/repos/amphp/byte-stream/zipball/4f0e968ba3798a423730f567b1b50d3441c16ddc", + "reference": "4f0e968ba3798a423730f567b1b50d3441c16ddc", "shasum": "" }, "require": { - "php": ">=5.4.0" + "amphp/amp": "^2", + "php": ">=7.1" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "amphp/php-cs-fixer-config": "dev-master", + "amphp/phpunit-util": "^1.4", + "friendsofphp/php-cs-fixer": "^2.3", + "jetbrains/phpstorm-stubs": "^2019.3", + "phpunit/phpunit": "^6 || ^7 || ^8", + "psalm/phar": "^3.11.4" }, "type": "library", "autoload": { + "files": [ + "lib/functions.php" + ], "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "Amp\\ByteStream\\": "lib" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], - "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", + "authors": [ + { + "name": "Aaron Piotrowski", + "email": "aaron@trowski.com" + }, + { + "name": "Niklas Keller", + "email": "me@kelunik.com" + } + ], + "description": "A stream abstraction to make working with non-blocking I/O simple.", + "homepage": "https://amphp.org/byte-stream", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "amp", + "amphp", + "async", + "io", + "non-blocking", + "stream" + ], + "support": { + "issues": "https://github.com/amphp/byte-stream/issues", + "source": "https://github.com/amphp/byte-stream/tree/v1.8.2" + }, + "funding": [ + { + "url": "https://github.com/amphp", + "type": "github" + } ], - "time": "2017-04-12 18:52:22" + "time": "2024-04-13T18:00:56+00:00" }, { - "name": "phpdocumentor/reflection-common", - "version": "dev-master", + "name": "clue/stdio-react", + "version": "v2.6.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "a046af61c36e9162372f205de091a1cab7340f1c" + "url": "https://github.com/clue/reactphp-stdio.git", + "reference": "dfa6c378aabdff718202d4e2453f752c38ea3399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/a046af61c36e9162372f205de091a1cab7340f1c", - "reference": "a046af61c36e9162372f205de091a1cab7340f1c", + "url": "https://api.github.com/repos/clue/reactphp-stdio/zipball/dfa6c378aabdff718202d4e2453f752c38ea3399", + "reference": "dfa6c378aabdff718202d4e2453f752c38ea3399", "shasum": "" }, "require": { - "php": ">=5.5" + "clue/term-react": "^1.0 || ^0.1.1", + "clue/utf8-react": "^1.0 || ^0.1", + "php": ">=5.3", + "react/event-loop": "^1.2", + "react/stream": "^1.2" }, "require-dev": { - "phpunit/phpunit": "^4.6" + "clue/arguments": "^2.0", + "clue/commander": "^1.2", + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.35" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "suggest": { + "ext-mbstring": "Using ext-mbstring should provide slightly better performance for handling I/O" }, + "type": "library", "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src" - ] + "Clue\\React\\Stdio\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -143,51 +208,67 @@ ], "authors": [ { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" + "name": "Christian Lück", + "email": "christian@clue.engineering" } ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org/", + "description": "Async, event-driven console input & output (STDIN, STDOUT) for truly interactive CLI applications, built on top of ReactPHP", + "homepage": "https://github.com/clue/reactphp-stdio", "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" + "async", + "autocomplete", + "autocompletion", + "cli", + "history", + "interactive", + "reactphp", + "readline", + "stdin", + "stdio", + "stdout" + ], + "support": { + "issues": "https://github.com/clue/reactphp-stdio/issues", + "source": "https://github.com/clue/reactphp-stdio/tree/v2.6.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } ], - "time": "2017-04-30 11:58:12" + "time": "2022-03-18T15:09:30+00:00" }, { - "name": "phpdocumentor/reflection-docblock", - "version": "3.1.1", + "name": "clue/term-react", + "version": "v1.4.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e" + "url": "https://github.com/clue/reactphp-term.git", + "reference": "00f297dc597eaee2ebf98af8f27cca5d21d60fa3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e", - "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e", + "url": "https://api.github.com/repos/clue/reactphp-term/zipball/00f297dc597eaee2ebf98af8f27cca5d21d60fa3", + "reference": "00f297dc597eaee2ebf98af8f27cca5d21d60fa3", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0@dev", - "phpdocumentor/type-resolver": "^0.2.0", - "webmozart/assert": "^1.0" + "php": ">=5.3", + "react/stream": "^1.2" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^4.4" + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/event-loop": "^1.2" }, "type": "library", "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "Clue\\React\\Term\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -196,46 +277,71 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Christian Lück", + "email": "christian@clue.engineering" } ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "description": "Streaming terminal emulator, built on top of ReactPHP.", + "homepage": "https://github.com/clue/reactphp-term", + "keywords": [ + "C0", + "CSI", + "ansi", + "apc", + "ascii", + "c1", + "control codes", + "dps", + "osc", + "pm", + "reactphp", + "streaming", + "terminal", + "vt100", + "xterm" + ], + "support": { + "issues": "https://github.com/clue/reactphp-term/issues", + "source": "https://github.com/clue/reactphp-term/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" + } + ], + "time": "2024-01-30T10:22:09+00:00" }, { - "name": "phpdocumentor/type-resolver", - "version": "0.2.1", + "name": "clue/utf8-react", + "version": "v1.3.0", "source": { "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb" + "url": "https://github.com/clue/reactphp-utf8.git", + "reference": "d5cd04d39cb5457aa5df830b7c4b301d2694217e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", - "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb", + "url": "https://api.github.com/repos/clue/reactphp-utf8/zipball/d5cd04d39cb5457aa5df830b7c4b301d2694217e", + "reference": "d5cd04d39cb5457aa5df830b7c4b301d2694217e", "shasum": "" }, "require": { - "php": ">=5.5", - "phpdocumentor/reflection-common": "^1.0" + "php": ">=5.3", + "react/stream": "^1.0 || ^0.7 || ^0.6 || ^0.5 || ^0.4 || ^0.3" }, "require-dev": { - "mockery/mockery": "^0.9.4", - "phpunit/phpunit": "^5.2||^4.8.24" + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", + "react/stream": "^1.0 || ^0.7" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "Clue\\React\\Utf8\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -244,46 +350,74 @@ ], "authors": [ { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "Streaming UTF-8 parser, built on top of ReactPHP.", + "homepage": "https://github.com/clue/reactphp-utf8", + "keywords": [ + "reactphp", + "streaming", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "issues": "https://github.com/clue/reactphp-utf8/issues", + "source": "https://github.com/clue/reactphp-utf8/tree/v1.3.0" + }, + "funding": [ + { + "url": "https://clue.engineering/support", + "type": "custom" + }, + { + "url": "https://github.com/clue", + "type": "github" } ], - "time": "2016-11-25 06:54:22" + "time": "2023-12-06T14:52:17+00:00" }, { - "name": "phpspec/prophecy", - "version": "dev-master", + "name": "composer/pcre", + "version": "3.3.1", "source": { "type": "git", - "url": "https://github.com/phpspec/prophecy.git", - "reference": "79db5dd907ee977039f77ac8471a739497463429" + "url": "https://github.com/composer/pcre.git", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/79db5dd907ee977039f77ac8471a739497463429", - "reference": "79db5dd907ee977039f77ac8471a739497463429", + "url": "https://api.github.com/repos/composer/pcre/zipball/63aaeac21d7e775ff9bc9d45021e1745c97521c4", + "reference": "63aaeac21d7e775ff9bc9d45021e1745c97521c4", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.3|^7.0", - "phpdocumentor/reflection-docblock": "^2.0|^3.0.2", - "sebastian/comparator": "^1.1|^2.0", - "sebastian/recursion-context": "^1.0|^2.0|^3.0" + "php": "^7.4 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<1.11.10" }, "require-dev": { - "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8 || ^5.6.5" + "phpstan/phpstan": "^1.11.10", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8 || ^9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-main": "3.x-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Composer\\Pcre\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -292,709 +426,756 @@ ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com/" - }, - { - "name": "Marcello Duarte", - "email": "marcello.duarte@gmail.com" + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" } ], - "description": "Highly opinionated mocking framework for PHP 5.3+", - "homepage": "https://github.com/phpspec/prophecy", + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", "keywords": [ - "Double", - "Dummy", - "fake", - "mock", - "spy", - "stub" + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.3.1" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } ], - "time": "2017-05-31 16:22:32" + "time": "2024-08-27T18:44:43+00:00" }, { - "name": "phpunit/dbunit", - "version": "2.0.x-dev", + "name": "composer/semver", + "version": "3.4.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/dbunit.git", - "reference": "4de41a2191690e8e1ad4d5197964f21cf1f975ba" + "url": "https://github.com/composer/semver.git", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/dbunit/zipball/4de41a2191690e8e1ad4d5197964f21cf1f975ba", - "reference": "4de41a2191690e8e1ad4d5197964f21cf1f975ba", + "url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6", + "reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6", "shasum": "" }, "require": { - "ext-pdo": "*", - "ext-simplexml": "*", - "php": "^5.4 || ^7.0", - "phpunit/phpunit": "^4.0 || ^5.0", - "symfony/yaml": "^2.1 || ^3.0" + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" }, - "bin": [ - "dbunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "3.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Composer\\Semver\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de/" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be/" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl/" } ], - "description": "DbUnit port for PHP/PHPUnit to support database interaction testing.", - "homepage": "https://github.com/sebastianbergmann/dbunit/", + "description": "Semver library that offers utilities, version constraint parsing and validation.", "keywords": [ - "database", - "testing", - "xunit" + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.4.2" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } ], - "time": "2017-01-04 08:08:01" + "time": "2024-07-12T11:35:52+00:00" }, { - "name": "phpunit/php-code-coverage", - "version": "4.0.x-dev", + "name": "composer/xdebug-handler", + "version": "3.0.5", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d" + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ef7b2f56815df854e66ceaee8ebe9393ae36a40d", - "reference": "ef7b2f56815df854e66ceaee8ebe9393ae36a40d", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6c1925561632e83d60a44492e0b344cf48ab85ef", + "reference": "6c1925561632e83d60a44492e0b344cf48ab85ef", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-xmlwriter": "*", - "php": "^5.6 || ^7.0", - "phpunit/php-file-iterator": "^1.3", - "phpunit/php-text-template": "^1.2", - "phpunit/php-token-stream": "^1.4.2 || ^2.0", - "sebastian/code-unit-reverse-lookup": "^1.0", - "sebastian/environment": "^1.3.2 || ^2.0", - "sebastian/version": "^1.0 || ^2.0" + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" }, "require-dev": { - "ext-xdebug": "^2.1.4", - "phpunit/phpunit": "^5.7" - }, - "suggest": { - "ext-xdebug": "^2.5.1" + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.0.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" } ], - "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", - "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "description": "Restarts a process without Xdebug.", "keywords": [ - "coverage", - "testing", - "xunit" + "Xdebug", + "performance" + ], + "support": { + "irc": "ircs://irc.libera.chat:6697/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.5" + }, + "funding": [ + { + "url": "https://packagist.com/", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } ], - "time": "2017-04-02 07:44:40" + "time": "2024-05-06T16:37:16+00:00" }, { - "name": "phpunit/php-file-iterator", - "version": "dev-master", + "name": "dnoegel/php-xdg-base-dir", + "version": "v0.1.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5" + "url": "https://github.com/dnoegel/php-xdg-base-dir.git", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5", - "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5", + "url": "https://api.github.com/repos/dnoegel/php-xdg-base-dir/zipball/8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", + "reference": "8f8a6e48c5ecb0f991c2fdcf5f154a47d85f9ffd", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.2" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4.x-dev" - } + "require-dev": { + "phpunit/phpunit": "~7.0|~6.0|~5.0|~4.8.35" }, + "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "XdgBaseDir\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" - } - ], - "description": "FilterIterator implementation that filters files based on a list of suffixes.", - "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", - "keywords": [ - "filesystem", - "iterator" + "MIT" ], - "time": "2016-10-03 07:40:28" + "description": "implementation of xdg base directory specification for php", + "support": { + "issues": "https://github.com/dnoegel/php-xdg-base-dir/issues", + "source": "https://github.com/dnoegel/php-xdg-base-dir/tree/v0.1.1" + }, + "time": "2019-12-04T15:06:13+00:00" }, { - "name": "phpunit/php-invoker", - "version": "1.1.x-dev", + "name": "doctrine/deprecations", + "version": "1.1.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "86074bf0fc2caf02ec8819a93f65a37cd0b44c8e" + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/86074bf0fc2caf02ec8819a93f65a37cd0b44c8e", - "reference": "86074bf0fc2caf02ec8819a93f65a37cd0b44c8e", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", "shasum": "" }, "require": { - "ext-pcntl": "*", - "php": ">=5.3.3", - "phpunit/php-timer": ">=1.0.6" + "php": "^7.1 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "~4" + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" - } - ], - "description": "Utility class for invoking callables with a timeout.", - "homepage": "https://github.com/sebastianbergmann/php-invoker/", - "keywords": [ - "process" + "MIT" ], - "time": "2015-06-21 13:32:55" + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" }, { - "name": "phpunit/php-text-template", - "version": "1.2.1", + "name": "doctrine/instantiator", + "version": "1.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" + "url": "https://github.com/doctrine/instantiator.git", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", - "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", + "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^11", + "ext-pdo": "*", + "ext-phar": "*", + "phpbench/phpbench": "^0.16 || ^1", + "phpstan/phpstan": "^1.4", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "vimeo/psalm": "^4.30 || ^5.4" }, "type": "library", "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "https://ocramius.github.io/" } ], - "description": "Simple template engine.", - "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://www.doctrine-project.org/projects/instantiator.html", "keywords": [ - "template" + "constructor", + "instantiate" ], - "time": "2015-06-21 13:50:34" + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2022-12-30T00:15:36+00:00" }, { - "name": "phpunit/php-timer", - "version": "dev-master", + "name": "evenement/evenement", + "version": "v3.0.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "d107f347d368dd8a384601398280c7c608390ab7" + "url": "https://github.com/igorw/evenement.git", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/d107f347d368dd8a384601398280c7c608390ab7", - "reference": "d107f347d368dd8a384601398280c7c608390ab7", + "url": "https://api.github.com/repos/igorw/evenement/zipball/0a16b0d71ab13284339abb99d9d2bd813640efbc", + "reference": "0a16b0d71ab13284339abb99d9d2bd813640efbc", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "^9 || ^6" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Evenement\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" } ], - "description": "Utility class for timing", - "homepage": "https://github.com/sebastianbergmann/php-timer/", + "description": "Événement is a very simple event dispatching library for PHP", "keywords": [ - "timer" + "event-dispatcher", + "event-emitter" ], - "time": "2017-03-07 15:42:04" + "support": { + "issues": "https://github.com/igorw/evenement/issues", + "source": "https://github.com/igorw/evenement/tree/v3.0.2" + }, + "time": "2023-08-08T05:53:35+00:00" }, { - "name": "phpunit/php-token-stream", - "version": "dev-master", + "name": "felixfbecker/advanced-json-rpc", + "version": "v3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "9ddb181faa4a3841fe131c357fd01de75cbb4da9" + "url": "https://github.com/felixfbecker/php-advanced-json-rpc.git", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/9ddb181faa4a3841fe131c357fd01de75cbb4da9", - "reference": "9ddb181faa4a3841fe131c357fd01de75cbb4da9", + "url": "https://api.github.com/repos/felixfbecker/php-advanced-json-rpc/zipball/b5f37dbff9a8ad360ca341f3240dc1c168b45447", + "reference": "b5f37dbff9a8ad360ca341f3240dc1c168b45447", "shasum": "" }, "require": { - "ext-tokenizer": "*", - "php": "^5.6 || ^7.0" + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "php": "^7.1 || ^8.0", + "phpdocumentor/reflection-docblock": "^4.3.4 || ^5.0.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "phpunit/phpunit": "^7.0 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "AdvancedJsonRpc\\": "lib/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "ISC" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Felix Becker", + "email": "felix.b@outlook.com" } ], - "description": "Wrapper around PHP's tokenizer extension.", - "homepage": "https://github.com/sebastianbergmann/php-token-stream/", - "keywords": [ - "tokenizer" - ], - "time": "2017-03-07 07:36:57" + "description": "A more advanced JSONRPC implementation", + "support": { + "issues": "https://github.com/felixfbecker/php-advanced-json-rpc/issues", + "source": "https://github.com/felixfbecker/php-advanced-json-rpc/tree/v3.2.1" + }, + "time": "2021-06-11T22:34:44+00:00" }, { - "name": "phpunit/phpunit", - "version": "5.7.x-dev", + "name": "felixfbecker/language-server-protocol", + "version": "v1.5.2", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "c0c61c97be37e1c77ab61ad73448e9208c05aade" + "url": "https://github.com/felixfbecker/php-language-server-protocol.git", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c0c61c97be37e1c77ab61ad73448e9208c05aade", - "reference": "c0c61c97be37e1c77ab61ad73448e9208c05aade", + "url": "https://api.github.com/repos/felixfbecker/php-language-server-protocol/zipball/6e82196ffd7c62f7794d778ca52b69feec9f2842", + "reference": "6e82196ffd7c62f7794d778ca52b69feec9f2842", "shasum": "" }, "require": { - "ext-dom": "*", - "ext-json": "*", - "ext-libxml": "*", - "ext-mbstring": "*", - "ext-xml": "*", - "myclabs/deep-copy": "~1.3", - "php": "^5.6 || ^7.0", - "phpspec/prophecy": "^1.6.2", - "phpunit/php-code-coverage": "^4.0.4", - "phpunit/php-file-iterator": "~1.4", - "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "^1.0.6", - "phpunit/phpunit-mock-objects": "^3.2", - "sebastian/comparator": "^1.2.4", - "sebastian/diff": "^1.4.3", - "sebastian/environment": "^1.3.4 || ^2.0", - "sebastian/exporter": "~2.0", - "sebastian/global-state": "^1.1", - "sebastian/object-enumerator": "~2.0", - "sebastian/resource-operations": "~1.0", - "sebastian/version": "~1.0.3|~2.0", - "symfony/yaml": "~2.1|~3.0" - }, - "conflict": { - "phpdocumentor/reflection-docblock": "3.0.2" + "php": ">=7.1" }, "require-dev": { - "ext-pdo": "*" - }, - "suggest": { - "ext-xdebug": "*", - "phpunit/php-invoker": "~1.1" + "phpstan/phpstan": "*", + "squizlabs/php_codesniffer": "^3.1", + "vimeo/psalm": "^4.0" }, - "bin": [ - "phpunit" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "5.7.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "LanguageServerProtocol\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "ISC" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Felix Becker", + "email": "felix.b@outlook.com" } ], - "description": "The PHP Unit Testing framework.", - "homepage": "https://phpunit.de/", + "description": "PHP classes for the Language Server Protocol", "keywords": [ - "phpunit", - "testing", - "xunit" + "language", + "microsoft", + "php", + "server" ], - "time": "2017-06-23 12:45:27" + "support": { + "issues": "https://github.com/felixfbecker/php-language-server-protocol/issues", + "source": "https://github.com/felixfbecker/php-language-server-protocol/tree/v1.5.2" + }, + "time": "2022-03-02T22:36:06+00:00" }, { - "name": "phpunit/phpunit-mock-objects", - "version": "3.4.x-dev", + "name": "fidry/cpu-core-counter", + "version": "1.2.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "4001a301f86fc006c32f532a741ab613f2bd8990" + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/4001a301f86fc006c32f532a741ab613f2bd8990", - "reference": "4001a301f86fc006c32f532a741ab613f2bd8990", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.0.2", - "php": "^5.6 || ^7.0", - "phpunit/php-text-template": "^1.2", - "sebastian/exporter": "^1.2 || ^2.0" - }, - "conflict": { - "phpunit/phpunit": "<5.4.0" + "php": "^7.2 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^5.4" - }, - "suggest": { - "ext-soap": "*" + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", - "role": "lead" + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" } ], - "description": "Mock Object library for PHPUnit", - "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", + "description": "Tiny utility to get the number of CPU cores.", "keywords": [ - "mock", - "xunit" + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } ], - "time": "2017-03-07 08:47:31" + "time": "2024-08-06T10:04:20+00:00" }, { - "name": "sebastian/code-unit-reverse-lookup", - "version": "dev-master", + "name": "jolicode/jolinotif", + "version": "v2.4.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "3488be0a7b346cd6e5361510ed07e88f9bea2e88" + "url": "https://github.com/jolicode/JoliNotif.git", + "reference": "a15bfc0d5aef432f150385924ede4e099643edb7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/3488be0a7b346cd6e5361510ed07e88f9bea2e88", - "reference": "3488be0a7b346cd6e5361510ed07e88f9bea2e88", + "url": "https://api.github.com/repos/jolicode/JoliNotif/zipball/a15bfc0d5aef432f150385924ede4e099643edb7", + "reference": "a15bfc0d5aef432f150385924ede4e099643edb7", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "php": ">=7.4", + "symfony/process": "^4.0|^5.0|^6.0" }, "require-dev": { - "phpunit/phpunit": "^5.7 || ^6.0" + "friendsofphp/php-cs-fixer": "^3.0", + "symfony/finder": "^5.0", + "symfony/phpunit-bridge": "^5.0" }, + "bin": [ + "jolinotif" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Joli\\JoliNotif\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Loïck Piera", + "email": "pyrech@gmail.com" } ], - "description": "Looks up which function or method a line of code belongs to", - "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", - "time": "2017-03-04 10:23:55" + "description": "Send desktop notifications on Windows, Linux, MacOS.", + "keywords": [ + "MAC", + "growl", + "linux", + "notification", + "windows" + ], + "support": { + "issues": "https://github.com/jolicode/JoliNotif/issues", + "source": "https://github.com/jolicode/JoliNotif/tree/v2.4.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/jolicode/jolinotif", + "type": "tidelift" + } + ], + "time": "2021-12-01T16:20:42+00:00" }, { - "name": "sebastian/comparator", - "version": "1.2.x-dev", + "name": "myclabs/deep-copy", + "version": "1.12.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "18a5d97c25f408f48acaf6d1b9f4079314c5996a" + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/18a5d97c25f408f48acaf6d1b9f4079314c5996a", - "reference": "18a5d97c25f408f48acaf6d1b9f4079314c5996a", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", "shasum": "" }, "require": { - "php": ">=5.3.3", - "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2 || ~2.0" + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3 <3.2.2" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpspec/prophecy": "^1.10", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.2.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], - "authors": [ - { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" - }, - { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" - }, + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" } ], - "description": "Provides the functionality to compare PHP values for equality", - "homepage": "http://www.github.com/sebastianbergmann/comparator", - "keywords": [ - "comparator", - "compare", - "equality" - ], - "time": "2017-03-07 10:34:43" + "time": "2024-06-12T14:39:25+00:00" }, { - "name": "sebastian/diff", - "version": "1.4.x-dev", + "name": "netresearch/jsonmapper", + "version": "v4.5.0", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" + "url": "https://github.com/cweiske/jsonmapper.git", + "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", - "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8e76efb98ee8b6afc54687045e1b8dba55ac76e5", + "reference": "8e76efb98ee8b6afc54687045e1b8dba55ac76e5", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "ext-json": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-spl": "*", + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "phpunit/phpunit": "~7.5 || ~8.0 || ~9.0 || ~10.0", + "squizlabs/php_codesniffer": "~3.5" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, "autoload": { - "classmap": [ - "src/" - ] + "psr-0": { + "JsonMapper": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "OSL-3.0" ], "authors": [ { - "name": "Kore Nordmann", - "email": "mail@kore-nordmann.de" - }, - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Christian Weiske", + "email": "cweiske@cweiske.de", + "homepage": "http://github.com/cweiske/jsonmapper/", + "role": "Developer" } ], - "description": "Diff implementation", - "homepage": "https://github.com/sebastianbergmann/diff", - "keywords": [ - "diff" - ], - "time": "2017-05-22 07:24:03" + "description": "Map nested JSON structures onto PHP classes", + "support": { + "email": "cweiske@cweiske.de", + "issues": "https://github.com/cweiske/jsonmapper/issues", + "source": "https://github.com/cweiske/jsonmapper/tree/v4.5.0" + }, + "time": "2024-09-08T10:13:13+00:00" }, { - "name": "sebastian/environment", - "version": "2.0.x-dev", + "name": "nikic/php-parser", + "version": "v4.19.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac" + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5795ffe5dc5b02460c3e34222fee8cbe245d8fac", - "reference": "5795ffe5dc5b02460c3e34222fee8cbe245d8fac", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", + "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0" + "ext-tokenizer": "*", + "php": ">=7.1" }, "require-dev": { - "phpunit/phpunit": "^5.0" + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "4.9-dev" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1002,40 +1183,41 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nikita Popov" } ], - "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "description": "A PHP parser written in PHP", "keywords": [ - "Xdebug", - "environment", - "hhvm" + "parser", + "php" ], - "time": "2016-11-26 07:53:53" + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + }, + "time": "2024-03-17T08:10:35+00:00" }, { - "name": "sebastian/exporter", - "version": "2.0.x-dev", + "name": "phar-io/manifest", + "version": "2.0.4", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "5e8e30670c3f36481e75211dbbcfd029a41ebf07" + "url": "https://github.com/phar-io/manifest.git", + "reference": "54750ef60c58e43759730615a392c31c80e23176" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/5e8e30670c3f36481e75211dbbcfd029a41ebf07", - "reference": "5e8e30670c3f36481e75211dbbcfd029a41ebf07", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", + "reference": "54750ef60c58e43759730615a392c31c80e23176", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0", - "sebastian/recursion-context": "^2.0" - }, - "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" + "ext-dom": "*", + "ext-libxml": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { @@ -1054,63 +1236,52 @@ ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" - }, - { - "name": "Volker Dusch", - "email": "github@wallbash.com" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" }, { - "name": "Bernhard Schussek", - "email": "bschussek@2bepublished.at" + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" }, { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - }, - { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "email": "sebastian@phpunit.de", + "role": "Developer" } ], - "description": "Provides the functionality to export PHP variables for visualization", - "homepage": "http://www.github.com/sebastianbergmann/exporter", - "keywords": [ - "export", - "exporter" + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } ], - "time": "2017-03-07 10:36:49" + "time": "2024-03-03T12:33:53+00:00" }, { - "name": "sebastian/global-state", - "version": "1.1.x-dev", + "name": "phar-io/version", + "version": "3.2.1", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "cea85a84b00f2795341ebbbca4fa396347f2494e" + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/cea85a84b00f2795341ebbbca4fa396347f2494e", - "reference": "cea85a84b00f2795341ebbbca4fa396347f2494e", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "phpunit/phpunit": "~4.2|~5.0" - }, - "suggest": { - "ext-uopz": "*" + "php": "^7.2 || ^8.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "classmap": [ "src/" @@ -1122,181 +1293,3187 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org/", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + }, + "time": "2024-05-21T05:55:05+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "153ae662783729388a584b4361f2545e4d841e3c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/153ae662783729388a584b4361f2545e4d841e3c", + "reference": "153ae662783729388a584b4361f2545e4d841e3c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.8.2" + }, + "time": "2024-02-23T11:10:43+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.30.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "51b95ec8670af41009e2b2b56873bad96682413e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/51b95ec8670af41009e2b2b56873bad96682413e", + "reference": "51b95ec8670af41009e2b2b56873bad96682413e", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.30.1" + }, + "time": "2024-09-07T20:13:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "9.2.31", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", + "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3", + "phpunit/php-file-iterator": "^3.0.3", + "phpunit/php-text-template": "^2.0.2", + "sebastian/code-unit-reverse-lookup": "^2.0.2", + "sebastian/complexity": "^2.0", + "sebastian/environment": "^5.1.2", + "sebastian/lines-of-code": "^1.0.3", + "sebastian/version": "^3.0.1", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:37:42+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "3.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2021-12-02T12:48:52+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "3.1.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:58:55+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T05:33:50+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:16:10+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "9.6.19", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", + "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.3.1 || ^2", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=7.3", + "phpunit/php-code-coverage": "^9.2.28", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-invoker": "^3.1.1", + "phpunit/php-text-template": "^2.0.3", + "phpunit/php-timer": "^5.0.2", + "sebastian/cli-parser": "^1.0.1", + "sebastian/code-unit": "^1.0.6", + "sebastian/comparator": "^4.0.8", + "sebastian/diff": "^4.0.3", + "sebastian/environment": "^5.1.3", + "sebastian/exporter": "^4.0.5", + "sebastian/global-state": "^5.0.1", + "sebastian/object-enumerator": "^4.0.3", + "sebastian/resource-operations": "^3.0.3", + "sebastian/type": "^3.2", + "sebastian/version": "^3.0.2" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.6-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2024-04-05T04:35:58+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/1.1.4" + }, + "time": "2021-05-03T11:20:27+00:00" + }, + { + "name": "react/event-loop", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/event-loop.git", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "suggest": { + "ext-pcntl": "For signal handling support when using the StreamSelectLoop" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\EventLoop\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "ReactPHP's core reactor event loop that libraries can use for evented I/O.", + "keywords": [ + "asynchronous", + "event-loop" + ], + "support": { + "issues": "https://github.com/reactphp/event-loop/issues", + "source": "https://github.com/reactphp/event-loop/tree/v1.5.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2023-11-13T13:48:05+00:00" + }, + { + "name": "react/stream", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/reactphp/stream.git", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/stream/zipball/1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "reference": "1e5b0acb8fe55143b5b426817155190eb6f5b18d", + "shasum": "" + }, + "require": { + "evenement/evenement": "^3.0 || ^2.0 || ^1.0", + "php": ">=5.3.8", + "react/event-loop": "^1.2" + }, + "require-dev": { + "clue/stream-filter": "~1.2", + "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "React\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering", + "homepage": "https://clue.engineering/" + }, + { + "name": "Cees-Jan Kiewiet", + "email": "reactphp@ceesjankiewiet.nl", + "homepage": "https://wyrihaximus.net/" + }, + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com", + "homepage": "https://sorgalla.com/" + }, + { + "name": "Chris Boden", + "email": "cboden@gmail.com", + "homepage": "https://cboden.dev/" + } + ], + "description": "Event-driven readable and writable streams for non-blocking I/O in ReactPHP", + "keywords": [ + "event-driven", + "io", + "non-blocking", + "pipe", + "reactphp", + "readable", + "stream", + "writable" + ], + "support": { + "issues": "https://github.com/reactphp/stream/issues", + "source": "https://github.com/reactphp/stream/tree/v1.4.0" + }, + "funding": [ + { + "url": "https://opencollective.com/reactphp", + "type": "open_collective" + } + ], + "time": "2024-06-11T12:45:25+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:27:43+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "1.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", + "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:08:54+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T05:30:19+00:00" + }, + { + "name": "sebastian/comparator", + "version": "4.0.8", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", + "reference": "fa0f136dd2334583309d32b62544682ee972b51a", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/diff": "^4.0", + "sebastian/exporter": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2022-09-14T12:41:17+00:00" + }, + { + "name": "sebastian/complexity", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", + "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:19:30+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", + "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:30:58+00:00" + }, + { + "name": "sebastian/environment", + "version": "5.1.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "http://www.github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:03:51+00:00" + }, + { + "name": "sebastian/exporter", + "version": "4.0.6", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", + "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:33:00+00:00" + }, + { + "name": "sebastian/global-state", + "version": "5.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^9.3" + }, + "suggest": { + "ext-uopz": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-02T06:35:11+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "1.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18 || ^5.0", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-12-22T06:20:34+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", + "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "shasum": "" + }, + "require": { + "php": ">=7.3", + "sebastian/object-reflector": "^2.0", + "sebastian/recursion-context": "^4.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:12:34+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "2.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:14:26+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "4.0.5", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:07:39+00:00" + }, + { + "name": "sebastian/resource-operations", + "version": "3.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/resource-operations.git", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides a list of PHP built-in functions that operate on resources", + "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2024-03-14T16:00:52+00:00" + }, + { + "name": "sebastian/type", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:13:03+00:00" + }, + { + "name": "sebastian/version", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c6c1022351a901512170118436c764e473f6de8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", + "reference": "c6c1022351a901512170118436c764e473f6de8c", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-09-28T06:39:44+00:00" + }, + { + "name": "spatie/array-to-xml", + "version": "2.17.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/array-to-xml.git", + "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/array-to-xml/zipball/5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "reference": "5cbec9c6ab17e320c58a259f0cebe88bde4a7c46", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": "^7.4|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "pestphp/pest": "^1.21", + "phpunit/phpunit": "^9.0", + "spatie/pest-plugin-snapshots": "^1.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\ArrayToXml\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://freek.dev/", + "role": "Developer" + } + ], + "description": "Convert an array to xml", + "homepage": "https://github.com/spatie/array-to-xml", + "keywords": [ + "array", + "convert", + "xml" + ], + "support": { + "source": "https://github.com/spatie/array-to-xml/tree/2.17.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-12-26T08:22:07+00:00" + }, + { + "name": "spatie/phpunit-watcher", + "version": "1.23.6", + "source": { + "type": "git", + "url": "https://github.com/spatie/phpunit-watcher.git", + "reference": "c192fff763810c8378511bcf0069df4b91478866" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/phpunit-watcher/zipball/c192fff763810c8378511bcf0069df4b91478866", + "reference": "c192fff763810c8378511bcf0069df4b91478866", + "shasum": "" + }, + "require": { + "clue/stdio-react": "^2.4", + "jolicode/jolinotif": "^2.2", + "php": "^7.2 | ^8.0 | ^8.1", + "symfony/console": "^5 | ^6", + "symfony/finder": "^5.4 | ^6", + "symfony/process": "^5.4 | ^6", + "symfony/yaml": "^5.2 | ^6", + "yosymfony/resource-watcher": "^2.0 | ^3.0" + }, + "conflict": { + "symfony/console": "<5.2", + "yosymfony/resource-watcher": "<2.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.6 | ^9.0" + }, + "bin": [ + "phpunit-watcher" + ], + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\PhpUnitWatcher\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be/", + "role": "Developer" + } + ], + "description": "Automatically rerun PHPUnit tests when source code changes", + "homepage": "https://github.com/spatie/phpunit-watcher", + "keywords": [ + "phpunit-watcher", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/phpunit-watcher/issues", + "source": "https://github.com/spatie/phpunit-watcher/tree/1.23.6" + }, + "time": "2022-01-31T11:57:13+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "06113cfdaf117fc2165f9cd040bd0f17fcd5242d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/06113cfdaf117fc2165f9cd040bd0f17fcd5242d", + "reference": "06113cfdaf117fc2165f9cd040bd0f17fcd5242d", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=7.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.4.0 || ^9.3.4 || ^10.5.32 || 11.3.3 - 11.5.28 || ^11.5.31" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-09-15T11:28:58+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.43", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/e86f8554de667c16dde8aeb89a3990cfde924df9", + "reference": "e86f8554de667c16dde8aeb89a3990cfde924df9", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com/", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.43" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-08-13T16:31:56+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/80d075412b557d41002320b96a096ca65aa2c98d", + "reference": "80d075412b557d41002320b96a096ca65aa2c98d", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-24T14:02:46+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v5.4.41", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "6d29dd9340b372fa603f04e6df4dd76bb808591e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/6d29dd9340b372fa603f04e6df4dd76bb808591e", + "reference": "6d29dd9340b372fa603f04e6df4dd76bb808591e", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "symfony/process": "^5.4|^6.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v5.4.41" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-06-28T09:36:24+00:00" + }, + { + "name": "symfony/finder", + "version": "v5.4.40", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "f51cff4687547641c7d8180d74932ab40b2205ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/f51cff4687547641c7d8180d74932ab40b2205ce", + "reference": "f51cff4687547641c7d8180d74932ab40b2205ce", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/finder/tree/v5.4.40" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-31T14:33:22+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "reference": "b9123926e3b7bc2f98c02ad54f6a4b02b91a8abe", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", + "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com/", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.31.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "reference": "60328e362d4c2c802a54fcbf04f9d3fb892b4cf8", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com/", "keywords": [ - "global state" + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.31.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2017-02-23 14:11:06" + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "sebastian/object-enumerator", - "version": "2.0.x-dev", + "name": "symfony/process", + "version": "v5.4.46", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "c956fe7a68318639f694fc6bba0c89b7cdf1b08c" + "url": "https://github.com/symfony/process.git", + "reference": "01906871cb9b5e3cf872863b91aba4ec9767daf4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/c956fe7a68318639f694fc6bba0c89b7cdf1b08c", - "reference": "c956fe7a68318639f694fc6bba0c89b7cdf1b08c", + "url": "https://api.github.com/repos/symfony/process/zipball/01906871cb9b5e3cf872863b91aba4ec9767daf4", + "reference": "01906871cb9b5e3cf872863b91aba4ec9767daf4", "shasum": "" }, "require": { - "php": "^5.6 || ^7.0", - "sebastian/recursion-context": "^2.0" - }, - "require-dev": { - "phpunit/phpunit": "^5.7" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, "autoload": { - "classmap": [ - "src/" + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Traverses array structures and object graphs to enumerate all referenced objects", - "homepage": "https://github.com/sebastianbergmann/object-enumerator/", - "time": "2017-03-07 10:37:45" + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.46" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-06T09:18:28+00:00" }, { - "name": "sebastian/recursion-context", - "version": "2.0.x-dev", + "name": "symfony/service-contracts", + "version": "v2.5.3", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "7e4d7c56f6e65d215f71ad913a5256e5439aca1c" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/7e4d7c56f6e65d215f71ad913a5256e5439aca1c", - "reference": "7e4d7c56f6e65d215f71ad913a5256e5439aca1c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/a2329596ddc8fd568900e3fc76cba42489ecc7f3", + "reference": "a2329596ddc8fd568900e3fc76cba42489ecc7f3", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" }, - "require-dev": { - "phpunit/phpunit": "~4.4" + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-main": "2.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" } }, "autoload": { - "classmap": [ - "src/" - ] + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Jeff Welch", - "email": "whatthejeff@gmail.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com/", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" }, { - "name": "Adam Harvey", - "email": "aharvey@php.net" + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } ], - "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2017-03-08 08:21:15" + "time": "2023-04-21T15:04:16+00:00" }, { - "name": "sebastian/resource-operations", - "version": "dev-master", + "name": "symfony/string", + "version": "v5.4.43", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "fadc83f7c41fb2924e542635fea47ae546816ece" + "url": "https://github.com/symfony/string.git", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/fadc83f7c41fb2924e542635fea47ae546816ece", - "reference": "fadc83f7c41fb2924e542635fea47ae546816ece", + "url": "https://api.github.com/repos/symfony/string/zipball/8be1d484951ff5ca995eaf8edcbcb8b9a5888450", + "reference": "8be1d484951ff5ca995eaf8edcbcb8b9a5888450", "shasum": "" }, "require": { - "php": ">=5.6.0" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } + "conflict": { + "symfony/translation-contracts": ">=3.0" }, + "require-dev": { + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" + }, + "type": "library", "autoload": { - "classmap": [ - "src/" + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "time": "2016-10-03 07:43:09" + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com/", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.43" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-08-01T10:24:28+00:00" }, { - "name": "sebastian/version", - "version": "dev-master", + "name": "symfony/yaml", + "version": "v5.4.40", "source": { "type": "git", - "url": "https://github.com/sebastianbergmann/version.git", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019" + "url": "https://github.com/symfony/yaml.git", + "reference": "81cad0ceab3d61fe14fe941ff18a230ac9c80f83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/99732be0ddb3361e16ad77b68ba41efc8e979019", - "reference": "99732be0ddb3361e16ad77b68ba41efc8e979019", + "url": "https://api.github.com/repos/symfony/yaml/zipball/81cad0ceab3d61fe14fe941ff18a230ac9c80f83", + "reference": "81cad0ceab3d61fe14fe941ff18a230ac9c80f83", "shasum": "" }, "require": { - "php": ">=5.6" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.3" + }, + "require-dev": { + "symfony/console": "^5.3|^6.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" }, + "bin": [ + "Resources/bin/yaml-lint" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com/", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.4.40" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" } + ], + "time": "2024-05-31T14:33:22+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.3", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" }, + "type": "library", "autoload": { "classmap": [ "src/" @@ -1308,51 +4485,110 @@ ], "authors": [ { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" } ], - "description": "Library that helps with managing the version number of Git-hosted PHP projects", - "homepage": "https://github.com/sebastianbergmann/version", - "time": "2016-10-03 07:35:21" + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.3" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2024-03-03T12:36:25+00:00" }, { - "name": "symfony/yaml", - "version": "3.4.x-dev", + "name": "vimeo/psalm", + "version": "5.26.1", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "1faeaf2aa8180967d80329213f77c1bcb75fe4fa" + "url": "https://github.com/vimeo/psalm.git", + "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/1faeaf2aa8180967d80329213f77c1bcb75fe4fa", - "reference": "1faeaf2aa8180967d80329213f77c1bcb75fe4fa", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", + "reference": "d747f6500b38ac4f7dfc5edbcae6e4b637d7add0", "shasum": "" }, "require": { - "php": ">=5.5.9" + "amphp/amp": "^2.4.2", + "amphp/byte-stream": "^1.5", + "composer-runtime-api": "^2", + "composer/semver": "^1.4 || ^2.0 || ^3.0", + "composer/xdebug-handler": "^2.0 || ^3.0", + "dnoegel/php-xdg-base-dir": "^0.1.1", + "ext-ctype": "*", + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-tokenizer": "*", + "felixfbecker/advanced-json-rpc": "^3.1", + "felixfbecker/language-server-protocol": "^1.5.2", + "fidry/cpu-core-counter": "^0.4.1 || ^0.5.1 || ^1.0.0", + "netresearch/jsonmapper": "^1.0 || ^2.0 || ^3.0 || ^4.0", + "nikic/php-parser": "^4.17", + "php": "^7.4 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0", + "sebastian/diff": "^4.0 || ^5.0 || ^6.0", + "spatie/array-to-xml": "^2.17.0 || ^3.0", + "symfony/console": "^4.1.6 || ^5.0 || ^6.0 || ^7.0", + "symfony/filesystem": "^5.4 || ^6.0 || ^7.0" + }, + "conflict": { + "nikic/php-parser": "4.17.0" + }, + "provide": { + "psalm/psalm": "self.version" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0" + "amphp/phpunit-util": "^2.0", + "bamarni/composer-bin-plugin": "^1.4", + "brianium/paratest": "^6.9", + "ext-curl": "*", + "mockery/mockery": "^1.5", + "nunomaduro/mock-final-classes": "^1.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpdoc-parser": "^1.6", + "phpunit/phpunit": "^9.6", + "psalm/plugin-mockery": "^1.1", + "psalm/plugin-phpunit": "^0.18", + "slevomat/coding-standard": "^8.4", + "squizlabs/php_codesniffer": "^3.6", + "symfony/process": "^4.4 || ^5.0 || ^6.0 || ^7.0" }, "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "ext-curl": "In order to send data to shepherd", + "ext-igbinary": "^2.0.5 is required, used to serialize caching data" }, - "type": "library", + "bin": [ + "psalm", + "psalm-language-server", + "psalm-plugin", + "psalm-refactor", + "psalter" + ], + "type": "project", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "5.x-dev", + "dev-4.x": "4.x-dev", + "dev-3.x": "3.x-dev", + "dev-2.x": "2.x-dev", + "dev-1.x": "1.x-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psalm\\": "src/Psalm/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -1360,43 +4596,52 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Matthew Brown" } ], - "description": "Symfony Yaml Component", - "homepage": "https://symfony.com/", - "time": "2017-06-24 09:47:31" + "description": "A static analysis tool for finding errors in PHP applications", + "keywords": [ + "code", + "inspection", + "php", + "static analysis" + ], + "support": { + "docs": "https://psalm.dev/docs", + "issues": "https://github.com/vimeo/psalm/issues", + "source": "https://github.com/vimeo/psalm" + }, + "time": "2024-09-08T18:53:08+00:00" }, { "name": "webmozart/assert", - "version": "dev-master", + "version": "1.11.0", "source": { "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "4a8bf11547e139e77b651365113fc12850c43d9a" + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/4a8bf11547e139e77b651365113fc12850c43d9a", - "reference": "4a8bf11547e139e77b651365113fc12850c43d9a", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", "shasum": "" }, "require": { - "php": "^5.3.3 || ^7.0" + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" }, "require-dev": { - "phpunit/phpunit": "^4.6", - "sebastian/version": "^1.0.1" + "phpunit/phpunit": "^8.5.13" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.10-dev" } }, "autoload": { @@ -1420,16 +4665,85 @@ "check", "validate" ], - "time": "2016-11-23 20:04:41" + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "yosymfony/resource-watcher", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/yosymfony/resource-watcher.git", + "reference": "2f197cee0231c06db865d4ad2d8d7cd3faead2f8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yosymfony/resource-watcher/zipball/2f197cee0231c06db865d4ad2d8d7cd3faead2f8", + "reference": "2f197cee0231c06db865d4ad2d8d7cd3faead2f8", + "shasum": "" + }, + "require": { + "php": ">=5.6", + "symfony/finder": "^2.7|^3.0|^4.0|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7", + "symfony/filesystem": "^2.7|^3.0|^4.0|^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Yosymfony\\ResourceWatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Victor Puertas", + "email": "vpgugr@gmail.com" + } + ], + "description": "A simple resource watcher using Symfony Finder", + "homepage": "http://yosymfony.com/", + "keywords": [ + "finder", + "resources", + "symfony", + "watcher" + ], + "support": { + "issues": "https://github.com/yosymfony/resource-watcher/issues", + "source": "https://github.com/yosymfony/resource-watcher/tree/master" + }, + "time": "2020-06-10T14:58:36+00:00" } ], "aliases": [], - "minimum-stability": "dev", - "stability-flags": [], + "minimum-stability": "stable", + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=5.6.0" + "php": "^7.4 || ^8.0", + "ext-curl": "*", + "ext-xml": "*", + "ext-simplexml": "*", + "ext-dom": "*" + }, + "platform-dev": {}, + "platform-overrides": { + "php": "7.4.27" }, - "platform-dev": [] + "plugin-api-version": "2.6.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 7b909b68..39da6f7b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,19 +1,33 @@ -version: '2' +# Copyright 1999-2025. WebPros International GmbH. +version: '3' services: plesk: - image: plesk/plesk:17.0 + image: plesk/plesk:latest logging: driver: none + ports: + ["8443:8443"] + tmpfs: + - /tmp + - /run + - /run/lock + volumes: + - /sys/fs/cgroup:/sys/fs/cgroup + cgroup: host tests: build: . environment: REMOTE_URL: https://plesk:8443 - REMOTE_PASSWORD: changeme - command: bash -c "cd /opt/api-php-lib && composer install && composer test" + REMOTE_PASSWORD: changeme1Q** + command: > + bash -c "cd /opt/api-php-lib + && composer install + && ./wait-for-plesk.sh + && composer lint + && composer test -- --testdox" depends_on: - plesk links: - plesk volumes: - .:/opt/api-php-lib - diff --git a/package.json b/package.json deleted file mode 100644 index 09527116..00000000 --- a/package.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "plesk-api-php-lib", - "version": "1.0.0", - "devDependencies": { - "grunt": "~0.4.5", - "grunt-contrib-watch": "~0.6.1", - "grunt-phpunit": "~0.3.5" - } -} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 00000000..fddc5cbe --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,27 @@ + + + + src + tests + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpunit-watcher.yml b/phpunit-watcher.yml new file mode 100644 index 00000000..9da731a5 --- /dev/null +++ b/phpunit-watcher.yml @@ -0,0 +1,4 @@ +# Copyright 1999-2025. WebPros International GmbH. +phpunit: + arguments: '--stop-on-failure' + timeout: 0 diff --git a/phpunit.xml.dist b/phpunit.xml.dist index a63df1a5..baaaa279 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,9 +1,23 @@ - - - - - tests/ - - + + + + + ./src + + + + + + + + ./tests + + + + + + + + diff --git a/psalm.xml b/psalm.xml new file mode 100644 index 00000000..ed069912 --- /dev/null +++ b/psalm.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/src/Api/AbstractStruct.php b/src/Api/AbstractStruct.php new file mode 100644 index 00000000..f63f51ef --- /dev/null +++ b/src/Api/AbstractStruct.php @@ -0,0 +1,76 @@ +{key($property)}; + } else { + /** @psalm-suppress PossiblyInvalidArgument */ + $classPropertyName = $this->underToCamel(str_replace('-', '_', $property)); + $value = $apiResponse->$property; + } + + $reflectionProperty = new \ReflectionProperty($this, $classPropertyName); + $propertyType = $reflectionProperty->getType(); + if (is_null($propertyType)) { + $docBlock = $reflectionProperty->getDocComment(); + $propertyType = preg_replace('/^.+ @var ([a-z]+) .+$/', '\1', $docBlock); + } else { + /** @psalm-suppress UndefinedMethod */ + $propertyType = $propertyType->getName(); + } + + if ('string' == $propertyType) { + $value = (string) $value; + } elseif ('int' == $propertyType) { + $value = (int) $value; + } elseif ('bool' == $propertyType) { + $value = in_array((string) $value, ['true', 'on', 'enabled']); + } else { + throw new \Exception("Unknown property type '$propertyType'."); + } + + $this->$classPropertyName = $value; + } + } + + /** + * Convert underscore separated words into camel case. + * + * @param string $under + * + * @return string + */ + private function underToCamel(string $under): string + { + $under = '_' . str_replace('_', ' ', strtolower($under)); + + return ltrim(str_replace(' ', '', ucwords($under)), '_'); + } +} diff --git a/src/Api/Client.php b/src/Api/Client.php new file mode 100644 index 00000000..c1dd350b --- /dev/null +++ b/src/Api/Client.php @@ -0,0 +1,577 @@ +host = $host; + $this->port = $port; + $this->protocol = $protocol; + } + + /** + * Setup credentials for authentication. + * + * @param string $login + * @param string $password + */ + public function setCredentials(string $login, string $password): void + { + $this->login = $login; + $this->password = $password; + } + + /** + * Define secret key for alternative authentication. + * + * @param string $secretKey + */ + public function setSecretKey(string $secretKey): void + { + $this->secretKey = $secretKey; + } + + /** + * Set proxy server for requests. + * + * @param string $proxy + */ + public function setProxy(string $proxy): void + { + $this->proxy = $proxy; + } + + /** + * Set default version for requests. + * + * @param string $version + */ + public function setVersion(string $version): void + { + $this->version = $version; + } + + /** + * Set custom function to verify response of API call according your own needs. + * Default verifying will be used if it is not specified. + * + * @param callable|null $function + */ + public function setVerifyResponse(?callable $function = null): void + { + $this->verifyResponseCallback = $function; + } + + /** + * Retrieve host used for communication. + * + * @return string + */ + public function getHost(): string + { + return $this->host; + } + + /** + * Retrieve port used for communication. + * + * @return int + */ + public function getPort(): int + { + return $this->port; + } + + /** + * Retrieve name of the protocol (http or https) used for communication. + * + * @return string + */ + public function getProtocol(): string + { + return $this->protocol; + } + + /** + * Retrieve XML template for packet. + * + * @param string|null $version + * + * @return SimpleXMLElement + */ + public function getPacket($version = null): SimpleXMLElement + { + $protocolVersion = !is_null($version) ? $version : $this->version; + $content = ""; + $content .= ''; + + return new SimpleXMLElement($content); + } + + /** + * Perform API request. + * + * @param string|array|SimpleXMLElement $request + * @param int $mode + * + * @return XmlResponse + * @throws \Exception + */ + public function request($request, int $mode = self::RESPONSE_SHORT): XmlResponse + { + if ($request instanceof SimpleXMLElement) { + $request = $request->asXml(); + } else { + $xml = $this->getPacket(); + + if (is_array($request)) { + $request = $this->arrayToXml($request, $xml)->asXML(); + } elseif (preg_match('/^[a-z]/', $request)) { + $request = $this->expandRequestShortSyntax($request, $xml); + } + } + + if ('sdk' == $this->protocol) { + $xml = $this->performSdkCall((string) $request); + } else { + $xml = $this->performHttpRequest((string) $request); + } + + $this->verifyResponseCallback + ? call_user_func($this->verifyResponseCallback, $xml) + : $this->verifyResponse($xml); + + $result = (self::RESPONSE_FULL === $mode) + ? $xml + : ($xml->xpath('//result') ?: [null])[0]; + + return new XmlResponse($result ? (string) $result->asXML() : ''); + } + + private function performSdkCall(string $request): XmlResponse + { + $version = ('' == $this->version) ? null : $this->version; + + $requestXml = new SimpleXMLElement($request); + $innerNodes = $requestXml->children(); + $innerXml = $innerNodes && count($innerNodes) > 0 && $innerNodes[0] ? $innerNodes[0]->asXml() : ''; + + /** @psalm-suppress UndefinedClass */ + $result = \pm_ApiRpc::getService($version)->call($innerXml, $this->login); + + return new XmlResponse($result ? (string) $result->asXML() : ''); + } + + /** + * Perform HTTP request to end-point. + * + * @param string $request + * + * @throws Client\Exception + * + * @return XmlResponse + */ + private function performHttpRequest($request) + { + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_URL, "$this->protocol://$this->host:$this->port/enterprise/control/agent.php"); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->getHeaders()); + curl_setopt($curl, CURLOPT_POSTFIELDS, $request); + + if ('' !== $this->proxy) { + curl_setopt($curl, CURLOPT_PROXY, $this->proxy); + } + + $result = curl_exec($curl); + + if (false === $result) { + throw new Client\Exception(curl_error($curl), curl_errno($curl)); + } + + curl_close($curl); + + return new XmlResponse((string) $result); + } + + /** + * Perform multiple API requests using single HTTP request. + * + * @param array $requests + * @param int $mode + * + * @throws Client\Exception + * + * @return array + */ + public function multiRequest(array $requests, int $mode = self::RESPONSE_SHORT): array + { + $requestXml = $this->getPacket(); + + 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(); + if (!$request) { + throw new Client\Exception('Failed to create an XML string for request'); + } + } elseif (preg_match('/^[a-z]/', $request)) { + $this->expandRequestShortSyntax($request, $requestXml); + } + } + } + + if ('sdk' == $this->protocol) { + throw new Client\Exception('Multi requests are not supported via SDK.'); + } else { + $xmlString = $requestXml->asXML(); + if (!$xmlString) { + throw new Client\Exception('Failed to create an XML string for request'); + } + $responseXml = $this->performHttpRequest($xmlString); + } + + return $this->splitResponseToArray($responseXml, $mode); + } + + private function splitResponseToArray(XmlResponse $responseXml, $mode = self::RESPONSE_SHORT): array + { + $responses = []; + + $nodes = $responseXml->children(); + if (!$nodes) { + return []; + } + + foreach ($nodes as $childNode) { + $dom = $this->getDomDocument($this->getPacket()); + if (!$dom) { + continue; + } + + $childDomNode = dom_import_simplexml($childNode); + if (!is_null($childDomNode)) { + $childDomNode = $dom->importNode($childDomNode, true); + $dom->documentElement->appendChild($childDomNode); + } + + $response = simplexml_load_string($dom->saveXML()); + if (!$response) { + return []; + } + + $responses[] = (self::RESPONSE_FULL == $mode) + ? $response + : ($response->xpath('//result') ?: [null])[0]; + } + + return $responses; + } + + private function getDomDocument(SimpleXMLElement $xml): ?DOMDocument + { + $dom = dom_import_simplexml($xml); + if (is_null($dom)) { + return null; + } + + return $dom->ownerDocument; + } + + /** + * Retrieve list of headers needed for request. + * + * @return array + */ + private function getHeaders() + { + $headers = [ + 'Content-Type: text/xml', + 'HTTP_PRETTY_PRINT: TRUE', + ]; + + if ($this->secretKey) { + $headers[] = "KEY: $this->secretKey"; + } else { + $headers[] = "HTTP_AUTH_LOGIN: $this->login"; + $headers[] = "HTTP_AUTH_PASSWD: $this->password"; + } + + return $headers; + } + + /** + * Verify that response does not contain errors. + * + * @param XmlResponse $xml + * + * @throws Exception + */ + private function verifyResponse($xml): void + { + if ($xml->system && $xml->system->status && 'error' == (string) $xml->system->status) { + 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') ?: [null])[0]; + $errorMessage = (string) ($xml->xpath('//errtext') ?: [null])[0]; + + throw new Exception($errorMessage, $errorCode); + } + } + + /** + * Expand short syntax (some.method.call) into full XML representation. + * + * @param string $request + * @param SimpleXMLElement $xml + * + * @return false|string + */ + private function expandRequestShortSyntax($request, SimpleXMLElement $xml) + { + $parts = explode('.', $request); + $node = $xml; + $lastParts = end($parts); + + foreach ($parts as $part) { + // phpcs:ignore + @list($name, $value) = explode('=', $part); + if ($part !== $lastParts) { + $node = $node->addChild($name); + } else { + $node->{$name} = (string) $value; + } + } + + return $xml->asXML(); + } + + /** + * Convert array to XML representation. + * + * @param array $array + * @param SimpleXMLElement $xml + * @param string $parentEl + * + * @return SimpleXMLElement + */ + private function arrayToXml(array $array, SimpleXMLElement $xml, $parentEl = null) + { + foreach ($array as $key => $value) { + $el = is_int($key) && $parentEl ? $parentEl : $key; + if (is_array($value)) { + $this->arrayToXml($value, $this->isAssocArray($value) ? $xml->addChild($el) : $xml, $el); + } elseif (!isset($xml->{$el})) { + $xml->{$el} = (string) $value; + } else { + $xml->{$el}[] = (string) $value; + } + } + + return $xml; + } + + /** + * @param array $array + * + * @return bool + */ + private function isAssocArray(array $array) + { + return $array && array_keys($array) !== range(0, count($array) - 1); + } + + /** + * @param string $name + * + * @return mixed + */ + private function getOperator(string $name) + { + if (!isset($this->operatorsCache[$name])) { + $className = '\\PleskX\\Api\\Operator\\' . $name; + /** @psalm-suppress InvalidStringClass */ + $this->operatorsCache[$name] = new $className($this); + } + + return $this->operatorsCache[$name]; + } + + public function server(): Operator\Server + { + return $this->getOperator('Server'); + } + + public function customer(): Operator\Customer + { + return $this->getOperator('Customer'); + } + + public function webspace(): Operator\Webspace + { + return $this->getOperator('Webspace'); + } + + public function subdomain(): Operator\Subdomain + { + return $this->getOperator('Subdomain'); + } + + public function dns(): Operator\Dns + { + return $this->getOperator('Dns'); + } + + public function dnsTemplate(): Operator\DnsTemplate + { + return $this->getOperator('DnsTemplate'); + } + + public function databaseServer(): Operator\DatabaseServer + { + return $this->getOperator('DatabaseServer'); + } + + public function mail(): Operator\Mail + { + return $this->getOperator('Mail'); + } + + public function certificate(): Operator\Certificate + { + return $this->getOperator('Certificate'); + } + + public function siteAlias(): Operator\SiteAlias + { + return $this->getOperator('SiteAlias'); + } + + public function ip(): Operator\Ip + { + return $this->getOperator('Ip'); + } + + public function eventLog(): Operator\EventLog + { + return $this->getOperator('EventLog'); + } + + public function secretKey(): Operator\SecretKey + { + return $this->getOperator('SecretKey'); + } + + public function ui(): Operator\Ui + { + return $this->getOperator('Ui'); + } + + public function servicePlan(): Operator\ServicePlan + { + return $this->getOperator('ServicePlan'); + } + + public function virtualDirectory(): Operator\VirtualDirectory + { + return $this->getOperator('VirtualDirectory'); + } + + public function database(): Operator\Database + { + return $this->getOperator('Database'); + } + + public function session(): Operator\Session + { + return $this->getOperator('Session'); + } + + public function locale(): Operator\Locale + { + return $this->getOperator('Locale'); + } + + public function logRotation(): Operator\LogRotation + { + return $this->getOperator('LogRotation'); + } + + public function protectedDirectory(): Operator\ProtectedDirectory + { + return $this->getOperator('ProtectedDirectory'); + } + + public function reseller(): Operator\Reseller + { + return $this->getOperator('Reseller'); + } + + public function resellerPlan(): Operator\ResellerPlan + { + return $this->getOperator('ResellerPlan'); + } + + public function aps(): Operator\Aps + { + return $this->getOperator('Aps'); + } + + public function servicePlanAddon(): Operator\ServicePlanAddon + { + return $this->getOperator('ServicePlanAddon'); + } + + public function site(): Operator\Site + { + return $this->getOperator('Site'); + } + + public function phpHandler(): Operator\PhpHandler + { + return $this->getOperator('PhpHandler'); + } +} diff --git a/src/Api/Client/Exception.php b/src/Api/Client/Exception.php new file mode 100644 index 00000000..f1cec03c --- /dev/null +++ b/src/Api/Client/Exception.php @@ -0,0 +1,11 @@ +login = $login; + } +} diff --git a/src/Api/Operator.php b/src/Api/Operator.php new file mode 100644 index 00000000..d3645d92 --- /dev/null +++ b/src/Api/Operator.php @@ -0,0 +1,106 @@ +client = $client; + + if ('' === $this->wrapperTag) { + $classNameParts = explode('\\', get_class($this)); + $this->wrapperTag = end($classNameParts); + $this->wrapperTag = strtolower(preg_replace('/([a-z])([A-Z])/', '\1-\2', $this->wrapperTag)); + } + } + + /** + * Perform plain API request. + * + * @param string|array $request + * @param int $mode + * + * @return XmlResponse + */ + public function request($request, $mode = Client::RESPONSE_SHORT): XmlResponse + { + $wrapperTag = $this->wrapperTag; + + if (is_array($request)) { + $request = [$wrapperTag => $request]; + } elseif (preg_match('/^[a-z]/', $request)) { + $request = "$wrapperTag.$request"; + } else { + $request = "<$wrapperTag>$request"; + } + + return $this->client->request($request, $mode); + } + + /** + * @param string $field + * @param int|string $value + * @param string $deleteMethodName + * + * @return bool + */ + protected function deleteBy(string $field, $value, string $deleteMethodName = 'del'): bool + { + $response = $this->request([ + $deleteMethodName => [ + 'filter' => [ + $field => $value, + ], + ], + ]); + + return 'ok' === (string) $response->status; + } + + /** + * @param string $structClass + * @param string $infoTag + * @param string|null $field + * @param int|string|null $value + * @param callable|null $filter + * + * @return array + */ + protected function getItems($structClass, $infoTag, $field = null, $value = null, ?callable $filter = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->{$field} = (string) $value; + } + + $getTag->addChild('dataset')->addChild($infoTag); + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult || !isset($xmlResult->data) || !isset($xmlResult->data->$infoTag)) { + continue; + } + if (!is_null($filter) && !$filter($xmlResult->data->$infoTag)) { + continue; + } + /** @psalm-suppress InvalidStringClass */ + $item = new $structClass($xmlResult->data->$infoTag); + if (isset($xmlResult->id) && property_exists($item, 'id')) { + $item->id = (int) $xmlResult->id; + } + $items[] = $item; + } + + return $items; + } +} diff --git a/src/PleskX/Api/Operator/Aps.php b/src/Api/Operator/Aps.php similarity index 60% rename from src/PleskX/Api/Operator/Aps.php rename to src/Api/Operator/Aps.php index b3fd926e..d2c44af8 100644 --- a/src/PleskX/Api/Operator/Aps.php +++ b/src/Api/Operator/Aps.php @@ -1,9 +1,8 @@ client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('generate')->addChild('info'); + + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param array $properties + * @param string|Struct\Info $certificate + * @param string|null $privateKey + */ + public function install(array $properties, $certificate, ?string $privateKey = null): bool + { + return $this->callApi('install', $properties, $certificate, $privateKey); + } + + /** + * @param array $properties + * @param Struct\Info $certificate + */ + public function update(array $properties, Struct\Info $certificate): bool + { + return $this->callApi('update', $properties, $certificate); + } + + /** + * @param string $method + * @param array $properties + * @param string|Struct\Info $certificate + * @param string|null $privateKey + */ + private function callApi(string $method, array $properties, $certificate, ?string $privateKey = null): bool + { + $packet = $this->client->getPacket(); + + $installTag = $packet->addChild($this->wrapperTag)->addChild($method); + foreach ($properties as $name => $value) { + $installTag->{$name} = $value; + } + + $contentTag = $installTag->addChild('content'); + if (is_string($certificate)) { + $contentTag->addChild('csr', $certificate); + $contentTag->addChild('pvt', $privateKey); + } elseif ($certificate instanceof \PleskX\Api\Struct\Certificate\Info) { + foreach ($certificate->getMapping() as $name => $value) { + $contentTag->{$name} = $value; + } + } + $result = $this->client->request($packet); + + return 'ok' == (string) $result->status; + } + + public function delete(string $name, array $properties): bool + { + $packet = $this->client->getPacket(); + + $removeTag = $packet->addChild($this->wrapperTag)->addChild('remove'); + $removeTag->addChild('filter')->addChild('name', $name); + + foreach ($properties as $name => $value) { + $removeTag->{$name} = $value; + } + + $result = $this->client->request($packet); + + return 'ok' == (string) $result->status; + } +} diff --git a/src/Api/Operator/Customer.php b/src/Api/Operator/Customer.php new file mode 100644 index 00000000..2136a491 --- /dev/null +++ b/src/Api/Operator/Customer.php @@ -0,0 +1,99 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add')->addChild('gen_info'); + + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo + */ + public function get(string $field, $value): Struct\GeneralInfo + { + $items = $this->getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); + + return reset($items); + } + + /** + * @return Struct\GeneralInfo[] + */ + public function getAll(): array + { + return $this->getItems(Struct\GeneralInfo::class, 'gen_info'); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function enable(string $field, $value): bool + { + return $this->setProperties($field, $value, ['status' => 0]); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function disable(string $field, $value): bool + { + return $this->setProperties($field, $value, ['status' => 16]); + } + + /** + * @param string $field + * @param int|string $value + * @param array $properties + * + * @return bool + */ + public function setProperties(string $field, $value, array $properties): bool + { + $packet = $this->client->getPacket(); + $setTag = $packet->addChild($this->wrapperTag)->addChild('set'); + $setTag->addChild('filter')->addChild($field, (string) $value); + $genInfoTag = $setTag->addChild('values')->addChild('gen_info'); + foreach ($properties as $property => $propertyValue) { + $genInfoTag->addChild($property, (string) $propertyValue); + } + + $response = $this->client->request($packet); + + return 'ok' === (string) $response->status; + } +} diff --git a/src/Api/Operator/Database.php b/src/Api/Operator/Database.php new file mode 100644 index 00000000..817adec5 --- /dev/null +++ b/src/Api/Operator/Database.php @@ -0,0 +1,149 @@ +process('add-db', $properties)); + } + + public function createUser(array $properties): Struct\UserInfo + { + return new Struct\UserInfo($this->process('add-db-user', $properties)); + } + + private function process(string $command, array $properties): XmlResponse + { + $packet = $this->client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild($command); + + foreach ($properties as $name => $value) { + if (false !== strpos($value, '&')) { + $info->$name = $value; + continue; + } + $info->{$name} = $value; + } + + return $this->client->request($packet); + } + + public function updateUser(array $properties): bool + { + $response = $this->process('set-db-user', $properties); + + return 'ok' === (string) $response->status; + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\UserInfo + */ + public function getUser(string $field, $value): Struct\UserInfo + { + $items = $this->getAllUsers($field, $value); + + return reset($items); + } + + /** + * @param string|null $field + * @param int|string $value + * + * @return Struct\Info[] + */ + public function getAll(?string $field, $value): array + { + $response = $this->getBy('get-db', $field, $value); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if ($xmlResult) { + $items[] = new Struct\Info($xmlResult); + } + } + + return $items; + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\UserInfo[] + */ + public function getAllUsers(string $field, $value): array + { + $response = $this->getBy('get-db-users', $field, $value); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if ($xmlResult) { + $items[] = new Struct\UserInfo($xmlResult); + } + } + + return $items; + } + + /** + * @param string $command + * @param string|null $field + * @param int|string $value + * + * @return XmlResponse + */ + private function getBy(string $command, ?string $field, $value): XmlResponse + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild($command); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->{$field} = (string) $value; + } + + return $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value, 'del-db'); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function deleteUser(string $field, $value): bool + { + return $this->deleteBy($field, $value, 'del-db-user'); + } +} diff --git a/src/Api/Operator/DatabaseServer.php b/src/Api/Operator/DatabaseServer.php new file mode 100644 index 00000000..03a5f115 --- /dev/null +++ b/src/Api/Operator/DatabaseServer.php @@ -0,0 +1,85 @@ +request('get-supported-types'); + + return (array) $response->type; + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getBy($field, $value); + + return reset($items); + } + + /** + * @return Struct\Info[] + */ + public function getAll(): array + { + return $this->getBy(); + } + + public function getDefault(string $type): Struct\Info + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get-default'); + $filterTag = $getTag->addChild('filter'); + /** @psalm-suppress UndefinedPropertyAssignment */ + $filterTag->type = $type; + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string|null $field + * @param int|string|null $value + * + * @return Struct\Info[] + */ + private function getBy($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->{$field} = (string) $value; + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + if (!is_null($xmlResult->data)) { + $item = new Struct\Info($xmlResult->data); + $item->id = (int) $xmlResult->id; + $items[] = $item; + } + } + + return $items; + } +} diff --git a/src/Api/Operator/Dns.php b/src/Api/Operator/Dns.php new file mode 100644 index 00000000..2d146d6c --- /dev/null +++ b/src/Api/Operator/Dns.php @@ -0,0 +1,132 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add_rec'); + + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + + return new Struct\Info($this->client->request($packet)); + } + + /** + * Send multiply records by one request. + * + * @param array $records + * + * @return \SimpleXMLElement[] + */ + public function bulkCreate(array $records): array + { + $packet = $this->client->getPacket(); + + foreach ($records as $properties) { + $info = $packet->addChild($this->wrapperTag)->addChild('add_rec'); + + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if ($xmlResult) { + $items[] = $xmlResult; + } + } + + return $items; + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info[] + */ + public function getAll(string $field, $value): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get_rec'); + + $filterTag = $getTag->addChild('filter'); + $filterTag->addChild($field, (string) $value); + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + if (!is_null($xmlResult->data)) { + $item = new Struct\Info($xmlResult->data); + $item->id = (int) $xmlResult->id; + $items[] = $item; + } + } + + return $items; + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value, 'del_rec'); + } + + /** + * Delete multiply records by one request. + * + * @param array $recordIds + * + * @return \SimpleXMLElement[] + */ + public function bulkDelete(array $recordIds): array + { + $packet = $this->client->getPacket(); + + foreach ($recordIds as $recordId) { + $packet->addChild($this->wrapperTag)->addChild('del_rec') + ->addChild('filter')->addChild('id', $recordId); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if ($xmlResult) { + $items[] = $xmlResult; + } + } + + return $items; + } +} diff --git a/src/Api/Operator/DnsTemplate.php b/src/Api/Operator/DnsTemplate.php new file mode 100644 index 00000000..d811c0d2 --- /dev/null +++ b/src/Api/Operator/DnsTemplate.php @@ -0,0 +1,93 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add_rec'); + + unset($properties['site-id'], $properties['site-alias-id']); + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + + return new Struct\Info($this->client->request($packet)); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info[] + */ + public function getAll($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get_rec'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->{$field} = (string) $value; + } + $getTag->addChild('template'); + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + if (!is_null($xmlResult->data)) { + $item = new Struct\Info($xmlResult->data); + $item->id = (int) $xmlResult->id; + $items[] = $item; + } + } + + return $items; + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + $packet = $this->client->getPacket(); + $delTag = $packet->addChild($this->wrapperTag)->addChild('del_rec'); + $delTag->addChild('filter')->addChild($field, (string) $value); + $delTag->addChild('template'); + + $response = $this->client->request($packet); + + return 'ok' === (string) $response->status; + } +} diff --git a/src/PleskX/Api/Operator/EventLog.php b/src/Api/Operator/EventLog.php similarity index 60% rename from src/PleskX/Api/Operator/EventLog.php rename to src/Api/Operator/EventLog.php index c62b297f..912e3628 100644 --- a/src/PleskX/Api/Operator/EventLog.php +++ b/src/Api/Operator/EventLog.php @@ -1,23 +1,23 @@ request('get'); - foreach ($response->event as $eventInfo) { + foreach ($response->event ?? [] as $eventInfo) { $records[] = new Struct\Event($eventInfo); } @@ -27,24 +27,20 @@ public function get() /** * @return Struct\DetailedEvent[] */ - public function getDetailedLog() + public function getDetailedLog(): array { $records = []; $response = $this->request('get_events'); - foreach ($response->event as $eventInfo) { + foreach ($response->event ?? [] as $eventInfo) { $records[] = new Struct\DetailedEvent($eventInfo); } return $records; } - /** - * @return int - */ - public function getLastId() + public function getLastId(): int { - return (int)$this->request('get-last-id')->getValue('id'); + return (int) $this->request('get-last-id')->getValue('id'); } - } diff --git a/src/Api/Operator/Ip.php b/src/Api/Operator/Ip.php new file mode 100644 index 00000000..ba1dfdcd --- /dev/null +++ b/src/Api/Operator/Ip.php @@ -0,0 +1,26 @@ +client->getPacket(); + $packet->addChild($this->wrapperTag)->addChild('get'); + $response = $this->client->request($packet); + + foreach ($response->addresses->ip_info ?? [] as $ipInfo) { + $ips[] = new Struct\Info($ipInfo); + } + + return $ips; + } +} diff --git a/src/Api/Operator/Locale.php b/src/Api/Operator/Locale.php new file mode 100644 index 00000000..c0b026c5 --- /dev/null +++ b/src/Api/Operator/Locale.php @@ -0,0 +1,35 @@ +client->getPacket(); + $filter = $packet->addChild($this->wrapperTag)->addChild('get')->addChild('filter'); + + if (!is_null($id)) { + $filter->addChild('id', $id); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + foreach ($response->locale->get->result ?? [] as $localeInfo) { + if (!is_null($localeInfo->info)) { + $locales[(string) $localeInfo->info->id] = new Struct\Info($localeInfo->info); + } + } + + return !is_null($id) ? reset($locales) : $locales; + } +} diff --git a/src/PleskX/Api/Operator/LogRotation.php b/src/Api/Operator/LogRotation.php similarity index 62% rename from src/PleskX/Api/Operator/LogRotation.php rename to src/Api/Operator/LogRotation.php index 6e407114..1014a287 100644 --- a/src/PleskX/Api/Operator/LogRotation.php +++ b/src/Api/Operator/LogRotation.php @@ -1,9 +1,8 @@ client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('create'); + + $filter = $info->addChild('filter'); + $filter->addChild('site-id', (string) $siteId); + $mailname = $filter->addChild('mailname'); + $mailname->addChild('name', $name); + if ($mailbox) { + $mailname->addChild('mailbox')->addChild('enabled', 'true'); + } + if (!empty($password)) { + /** @psalm-suppress UndefinedPropertyAssignment */ + $mailname->addChild('password')->value = $password; + } + + $response = $this->client->request($packet); + + /** @psalm-suppress PossiblyNullArgument */ + return new Struct\Info($response->mailname); + } + + /** + * @param string $field + * @param int|string $value + * @param int $siteId + * + * @return bool + */ + public function delete(string $field, $value, int $siteId): bool + { + $packet = $this->client->getPacket(); + $filter = $packet->addChild($this->wrapperTag)->addChild('remove')->addChild('filter'); + + $filter->addChild('site-id', (string) $siteId); + $filter->{$field} = (string) $value; + + $response = $this->client->request($packet); + + return 'ok' === (string) $response->status; + } + + public function get(string $name, int $siteId): Struct\GeneralInfo + { + $items = $this->getAll($siteId, $name); + + return reset($items); + } + + /** + * @param int $siteId + * @param string|null $name + * + * @return Struct\GeneralInfo[] + */ + public function getAll(int $siteId, $name = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get_info'); + + $filterTag = $getTag->addChild('filter'); + $filterTag->addChild('site-id', (string) $siteId); + if (!is_null($name)) { + $filterTag->addChild('name', $name); + } + + $response = $this->client->request($packet, Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult || !isset($xmlResult->mailname)) { + continue; + } + $item = new Struct\GeneralInfo($xmlResult->mailname); + $items[] = $item; + } + + return $items; + } +} diff --git a/src/Api/Operator/PhpHandler.php b/src/Api/Operator/PhpHandler.php new file mode 100644 index 00000000..c8bd4889 --- /dev/null +++ b/src/Api/Operator/PhpHandler.php @@ -0,0 +1,62 @@ +client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + $filterTag = $getTag->addChild('filter'); + + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $response = $this->client->request($packet, Client::RESPONSE_FULL); + $xmlResult = ($response->xpath('//result') ?: [null])[0]; + + return $xmlResult ? new Info($xmlResult) : null; + } + + /** + * @param string|null $field + * @param int|string $value + * + * @return Info[] + */ + public function getAll($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $response = $this->client->request($packet, Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + $item = new Info($xmlResult); + $items[] = $item; + } + + return $items; + } +} diff --git a/src/Api/Operator/ProtectedDirectory.php b/src/Api/Operator/ProtectedDirectory.php new file mode 100644 index 00000000..4c6d78b6 --- /dev/null +++ b/src/Api/Operator/ProtectedDirectory.php @@ -0,0 +1,118 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add'); + + $info->addChild('site-id', (string) $siteId); + $info->addChild('name', $name); + $info->addChild('header', $header); + + return new Struct\Info($this->client->request($packet)); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value, 'delete'); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\DataInfo + */ + public function get(string $field, $value): Struct\DataInfo + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\DataInfo[] + */ + public function getAll(string $field, $value): array + { + $response = $this->getBy('get', $field, $value); + $items = []; + foreach ((array) $response->xpath('//result/data') as $xmlResult) { + if (!$xmlResult) { + continue; + } + $items[] = new Struct\DataInfo($xmlResult); + } + + return $items; + } + + /** + * @param Struct\Info $protectedDirectory + * @param string $login + * @param string $password + * + * @return Struct\UserInfo + * @psalm-suppress UndefinedPropertyAssignment + */ + public function addUser($protectedDirectory, $login, $password) + { + $packet = $this->client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add-user'); + + $info->{'pd-id'} = (string) $protectedDirectory->id; + $info->login = $login; + $info->password = $password; + + return new Struct\UserInfo($this->client->request($packet)); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function deleteUser($field, $value) + { + return $this->deleteBy($field, $value, 'delete-user'); + } + + /** + * @param string $command + * @param string $field + * @param int|string $value + * + * @return \PleskX\Api\XmlResponse + */ + private function getBy(string $command, string $field, $value) + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild($command); + + $filterTag = $getTag->addChild('filter'); + $filterTag->{$field} = (string) $value; + + return $this->client->request($packet, Client::RESPONSE_FULL); + } +} diff --git a/src/Api/Operator/Reseller.php b/src/Api/Operator/Reseller.php new file mode 100644 index 00000000..95671492 --- /dev/null +++ b/src/Api/Operator/Reseller.php @@ -0,0 +1,83 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add')->addChild('gen-info'); + + foreach ($properties as $name => $value) { + $info->{$name} = $value; + } + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo + */ + public function get(string $field, $value): Struct\GeneralInfo + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo[] + */ + public function getAll($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $datasetTag = $getTag->addChild('dataset'); + $datasetTag->addChild('gen-info'); + $datasetTag->addChild('permissions'); + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult || !$xmlResult->data) { + continue; + } + + $item = new Struct\GeneralInfo($xmlResult->data); + $item->id = (int) $xmlResult->id; + $items[] = $item; + } + + return $items; + } +} diff --git a/src/PleskX/Api/Operator/ResellerPlan.php b/src/Api/Operator/ResellerPlan.php similarity index 63% rename from src/PleskX/Api/Operator/ResellerPlan.php rename to src/Api/Operator/ResellerPlan.php index 78ae7710..fd544e1d 100644 --- a/src/PleskX/Api/Operator/ResellerPlan.php +++ b/src/Api/Operator/ResellerPlan.php @@ -1,9 +1,8 @@ client->getPacket(); + $createTag = $packet->addChild($this->wrapperTag)->addChild('create'); + + if ('' !== $ipAddress) { + $createTag->addChild('ip_address', $ipAddress); + } + + if ('' !== $description) { + $createTag->addChild('description', $description); + } + + $response = $this->client->request($packet); + + return (string) $response->key; + } + + public function delete(string $keyId): bool + { + return $this->deleteBy('key', $keyId, 'delete'); + } + + public function get(string $keyId): Struct\Info + { + $items = $this->getBy($keyId); + + return reset($items); + } + + /** + * @return Struct\Info[] + */ + public function getAll(): array + { + return $this->getBy(); + } + + /** + * @param string|null $keyId + * + * @return Struct\Info[] + */ + public function getBy($keyId = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get_info'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($keyId)) { + $filterTag->addChild('key', $keyId); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result/key_info') as $keyInfo) { + if (!$keyInfo) { + continue; + } + $items[] = new Struct\Info($keyInfo); + } + + return $items; + } +} diff --git a/src/Api/Operator/Server.php b/src/Api/Operator/Server.php new file mode 100644 index 00000000..b4f7624d --- /dev/null +++ b/src/Api/Operator/Server.php @@ -0,0 +1,143 @@ +client->getPacket(); + $packet->addChild($this->wrapperTag)->addChild('get_protos'); + $response = $this->client->request($packet); + + /** @psalm-suppress PossiblyNullPropertyFetch */ + return (array) $response->protos->proto; + } + + public function getGeneralInfo(): Struct\GeneralInfo + { + return new Struct\GeneralInfo($this->getInfo('gen_info')); + } + + public function getPreferences(): Struct\Preferences + { + return new Struct\Preferences($this->getInfo('prefs')); + } + + public function getAdmin(): Struct\Admin + { + return new Struct\Admin($this->getInfo('admin')); + } + + public function getKeyInfo(): array + { + $keyInfo = []; + $keyInfoXml = $this->getInfo('key'); + + foreach ($keyInfoXml->property ?? [] as $property) { + $keyInfo[(string) $property->name] = (string) $property->value; + } + + return $keyInfo; + } + + public function getComponents(): array + { + $components = []; + $componentsXml = $this->getInfo('components'); + + foreach ($componentsXml->component ?? [] as $component) { + $components[(string) $component->name] = (string) $component->version; + } + + return $components; + } + + public function getServiceStates(): array + { + $states = []; + $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, + ]; + } + + return $states; + } + + public function getSessionPreferences(): Struct\SessionPreferences + { + return new Struct\SessionPreferences($this->getInfo('session_setup')); + } + + public function getShells(): array + { + $shells = []; + $shellsXml = $this->getInfo('shells'); + + foreach ($shellsXml->shell ?? [] as $shell) { + $shells[(string) $shell->name] = (string) $shell->path; + } + + return $shells; + } + + public function getNetworkInterfaces(): array + { + $interfacesXml = $this->getInfo('interfaces'); + + return (array) $interfacesXml->interface; + } + + public function getStatistics(): Struct\Statistics + { + return new Struct\Statistics($this->getInfo('stat')); + } + + public function getSiteIsolationConfig(): array + { + $config = []; + $configXml = $this->getInfo('site-isolation-config'); + + foreach ($configXml->property ?? [] as $property) { + $config[(string) $property->name] = (string) $property->value; + } + + return $config; + } + + public function getUpdatesInfo(): Struct\UpdatesInfo + { + return new Struct\UpdatesInfo($this->getInfo('updates')); + } + + public function createSession(string $login, string $clientIp): string + { + $packet = $this->client->getPacket(); + $sessionNode = $packet->addChild($this->wrapperTag)->addChild('create_session'); + $sessionNode->addChild('login', $login); + $dataNode = $sessionNode->addChild('data'); + $dataNode->addChild('user_ip', base64_encode($clientIp)); + $dataNode->addChild('source_server'); + $response = $this->client->request($packet); + + return (string) $response->id; + } + + private function getInfo(string $operation): XmlResponse + { + $packet = $this->client->getPacket(); + $packet->addChild($this->wrapperTag)->addChild('get')->addChild($operation); + $response = $this->client->request($packet); + + return $response->$operation; + } +} diff --git a/src/Api/Operator/ServicePlan.php b/src/Api/Operator/ServicePlan.php new file mode 100644 index 00000000..f1f03697 --- /dev/null +++ b/src/Api/Operator/ServicePlan.php @@ -0,0 +1,77 @@ +request(['add' => $properties]); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getBy($field, $value); + + return reset($items); + } + + /** + * @return Struct\Info[] + */ + public function getAll(): array + { + return $this->getBy(); + } + + /** + * @param string|null $field + * @param int|string|null $value + * + * @return Struct\Info[] + */ + private function getBy($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + $items[] = new Struct\Info($xmlResult); + } + + return $items; + } +} diff --git a/src/Api/Operator/ServicePlanAddon.php b/src/Api/Operator/ServicePlanAddon.php new file mode 100644 index 00000000..5c7a0cd9 --- /dev/null +++ b/src/Api/Operator/ServicePlanAddon.php @@ -0,0 +1,77 @@ +request(['add' => $properties]); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getBy($field, $value); + + return reset($items); + } + + /** + * @return Struct\Info[] + */ + public function getAll(): array + { + return $this->getBy(); + } + + /** + * @param string|null $field + * @param int|string|null $value + * + * @return Struct\Info[] + */ + private function getBy($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + $items[] = new Struct\Info($xmlResult); + } + + return $items; + } +} diff --git a/src/Api/Operator/Session.php b/src/Api/Operator/Session.php new file mode 100644 index 00000000..0cb74473 --- /dev/null +++ b/src/Api/Operator/Session.php @@ -0,0 +1,47 @@ +client->getPacket(); + $creator = $packet->addChild('server')->addChild('create_session'); + + $creator->addChild('login', $username); + $loginData = $creator->addChild('data'); + + $loginData->addChild('user_ip', base64_encode($userIp)); + $loginData->addChild('source_server', ''); + + $response = $this->client->request($packet); + + return (string) $response->id; + } + + /** + * @return Struct\Info[] + */ + public function get(): array + { + $sessions = []; + $response = $this->request('get'); + + foreach ($response->session ?? [] as $sessionInfo) { + $sessions[(string) $sessionInfo->id] = new Struct\Info($sessionInfo); + } + + return $sessions; + } + + public function terminate(string $sessionId): bool + { + $response = $this->request("terminate.session-id=$sessionId"); + + return 'ok' === (string) $response->status; + } +} diff --git a/src/Api/Operator/Site.php b/src/Api/Operator/Site.php new file mode 100644 index 00000000..4a1e5cca --- /dev/null +++ b/src/Api/Operator/Site.php @@ -0,0 +1,94 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add'); + + $infoGeneral = $info->addChild('gen_setup'); + foreach ($properties as $name => $value) { + if (!is_scalar($value)) { + continue; + } + $infoGeneral->{$name} = (string) $value; + } + + // set hosting properties + if (isset($properties[static::PROPERTIES_HOSTING]) && is_array($properties[static::PROPERTIES_HOSTING])) { + $hostingNode = $info->addChild('hosting')->addChild('vrt_hst'); + foreach ($properties[static::PROPERTIES_HOSTING] as $name => $value) { + $propertyNode = $hostingNode->addChild('property'); + /** @psalm-suppress UndefinedPropertyAssignment */ + $propertyNode->name = $name; + /** @psalm-suppress UndefinedPropertyAssignment */ + $propertyNode->value = $value; + } + } + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return ?Struct\GeneralInfo + */ + public function get(string $field, $value): ?Struct\GeneralInfo + { + $items = $this->getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); + + return reset($items) ?: null; + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\HostingInfo|null + */ + public function getHosting(string $field, $value): ?Struct\HostingInfo + { + $items = $this->getItems( + Struct\HostingInfo::class, + 'hosting', + $field, + $value, + function (\SimpleXMLElement $node) { + return isset($node->vrt_hst); + } + ); + + return empty($items) ? null : reset($items); + } + + /** + * @return Struct\GeneralInfo[] + */ + public function getAll(): array + { + return $this->getItems(Struct\GeneralInfo::class, 'gen_info'); + } +} diff --git a/src/Api/Operator/SiteAlias.php b/src/Api/Operator/SiteAlias.php new file mode 100644 index 00000000..2899abda --- /dev/null +++ b/src/Api/Operator/SiteAlias.php @@ -0,0 +1,85 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('create'); + + if (count($preferences) > 0) { + $prefs = $info->addChild('pref'); + + foreach ($preferences as $key => $value) { + $prefs->addChild($key, is_bool($value) ? ($value ? '1' : '0') : $value); + } + } + + $info->addChild('site-id', $properties['site-id']); + $info->addChild('name', $properties['name']); + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value, 'delete'); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo + */ + public function get(string $field, $value): Struct\GeneralInfo + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo[] + */ + public function getAll($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->{$field} = (string) $value; + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult) { + continue; + } + if (!is_null($xmlResult->info)) { + $item = new Struct\GeneralInfo($xmlResult->info); + $items[] = $item; + } + } + + return $items; + } +} diff --git a/src/Api/Operator/Subdomain.php b/src/Api/Operator/Subdomain.php new file mode 100644 index 00000000..ca23f7d2 --- /dev/null +++ b/src/Api/Operator/Subdomain.php @@ -0,0 +1,88 @@ +client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add'); + + foreach ($properties as $name => $value) { + if (is_array($value)) { + foreach ($value as $propertyName => $propertyValue) { + $property = $info->addChild($name); + /** @psalm-suppress UndefinedPropertyAssignment */ + $property->name = $propertyName; + /** @psalm-suppress UndefinedPropertyAssignment */ + $property->value = $propertyValue; + } + continue; + } + $info->{$name} = $value; + } + + $response = $this->client->request($packet); + + return new Struct\Info($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info + */ + public function get(string $field, $value): Struct\Info + { + $items = $this->getAll($field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Info[] + */ + public function getAll($field = null, $value = null): array + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $filterTag = $getTag->addChild('filter'); + if (!is_null($field)) { + $filterTag->addChild($field, (string) $value); + } + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + $items = []; + foreach ((array) $response->xpath('//result') as $xmlResult) { + if (!$xmlResult || empty($xmlResult->data)) { + continue; + } + $item = new Struct\Info($xmlResult->data); + $item->id = (int) $xmlResult->id; + $items[] = $item; + } + + return $items; + } +} diff --git a/src/Api/Operator/Ui.php b/src/Api/Operator/Ui.php new file mode 100644 index 00000000..c93dc3ce --- /dev/null +++ b/src/Api/Operator/Ui.php @@ -0,0 +1,45 @@ +request('get-navigation'); + + /** @psalm-suppress ImplicitToStringCast, PossiblyNullArgument */ + return unserialize(base64_decode($response->navigation)); + } + + public function createCustomButton(string $owner, array $properties): int + { + $packet = $this->client->getPacket(); + $buttonNode = $packet->addChild($this->wrapperTag)->addChild('create-custombutton'); + $buttonNode->addChild('owner')->addChild($owner); + $propertiesNode = $buttonNode->addChild('properties'); + + foreach ($properties as $name => $value) { + $propertiesNode->{$name} = $value; + } + + $response = $this->client->request($packet); + + return (int) $response->id; + } + + public function getCustomButton(int $id): Struct\CustomButton + { + $response = $this->request("get-custombutton.filter.custombutton-id=$id"); + + return new Struct\CustomButton($response); + } + + public function deleteCustomButton(int $id): bool + { + return $this->deleteBy('custombutton-id', $id, 'delete-custombutton'); + } +} diff --git a/src/Api/Operator/VirtualDirectory.php b/src/Api/Operator/VirtualDirectory.php new file mode 100644 index 00000000..081cd2d1 --- /dev/null +++ b/src/Api/Operator/VirtualDirectory.php @@ -0,0 +1,9 @@ +request('get-permission-descriptor.filter'); + + return new Struct\PermissionDescriptor($response); + } + + public function getLimitDescriptor(): Struct\LimitDescriptor + { + $response = $this->request('get-limit-descriptor.filter'); + + return new Struct\LimitDescriptor($response); + } + + public function getPhysicalHostingDescriptor(): Struct\PhysicalHostingDescriptor + { + $response = $this->request('get-physical-hosting-descriptor.filter'); + + return new Struct\PhysicalHostingDescriptor($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\PhpSettings + */ + public function getPhpSettings(string $field, $value): Struct\PhpSettings + { + $packet = $this->client->getPacket(); + $getTag = $packet->addChild($this->wrapperTag)->addChild('get'); + + $getTag->addChild('filter')->addChild($field, (string) $value); + $getTag->addChild('dataset')->addChild('php-settings'); + + $response = $this->client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); + + return new Struct\PhpSettings($response); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\Limits + */ + public function getLimits(string $field, $value): Struct\Limits + { + $items = $this->getItems(Struct\Limits::class, 'limits', $field, $value); + + return reset($items); + } + + /** + * @param array $properties + * @param array|null $hostingProperties + * @param string $planName + * + * @return Struct\Info + */ + public function create(array $properties, ?array $hostingProperties = null, string $planName = ''): Struct\Info + { + $packet = $this->client->getPacket(); + $info = $packet->addChild($this->wrapperTag)->addChild('add'); + + $infoGeneral = $info->addChild('gen_setup'); + foreach ($properties as $name => $value) { + if (is_array($value)) { + continue; + } else { + $infoGeneral->addChild($name, (string) $value); + } + } + + if ($hostingProperties) { + $infoHosting = $info->addChild('hosting')->addChild('vrt_hst'); + foreach ($hostingProperties as $name => $value) { + $property = $infoHosting->addChild('property'); + /** @psalm-suppress UndefinedPropertyAssignment */ + $property->name = $name; + /** @psalm-suppress UndefinedPropertyAssignment */ + $property->value = $value; + } + + if (isset($properties['ip_address'])) { + foreach ((array) $properties['ip_address'] as $ipAddress) { + $infoHosting->addChild('ip_address', $ipAddress); + } + } + } + + if ('' !== $planName) { + $info->addChild('plan-name', $planName); + } + + $response = $this->client->request($packet); + + return new Struct\Info($response, $properties['name'] ?? ''); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function delete(string $field, $value): bool + { + return $this->deleteBy($field, $value); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\GeneralInfo + */ + public function get(string $field, $value): Struct\GeneralInfo + { + $items = $this->getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); + + return reset($items); + } + + /** + * @return Struct\GeneralInfo[] + */ + public function getAll(): array + { + return $this->getItems(Struct\GeneralInfo::class, 'gen_info'); + } + + /** + * @param string $field + * @param int|string $value + * + * @return Struct\DiskUsage + */ + public function getDiskUsage(string $field, $value): Struct\DiskUsage + { + $items = $this->getItems(Struct\DiskUsage::class, 'disk_usage', $field, $value); + + return reset($items); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function enable(string $field, $value): bool + { + return $this->setProperties($field, $value, ['status' => 0]); + } + + /** + * @param string $field + * @param int|string $value + * + * @return bool + */ + public function disable(string $field, $value): bool + { + return $this->setProperties($field, $value, ['status' => 16]); + } + + /** + * @param string $field + * @param int|string $value + * @param array $properties + * + * @return bool + */ + public function setProperties(string $field, $value, array $properties): bool + { + $packet = $this->client->getPacket(); + $setTag = $packet->addChild($this->wrapperTag)->addChild('set'); + $setTag->addChild('filter')->addChild($field, (string) $value); + $genInfoTag = $setTag->addChild('values')->addChild('gen_setup'); + foreach ($properties as $property => $propertyValue) { + $genInfoTag->addChild($property, (string) $propertyValue); + } + + $response = $this->client->request($packet); + + return 'ok' === (string) $response->status; + } +} diff --git a/src/Api/Struct/Certificate/Info.php b/src/Api/Struct/Certificate/Info.php new file mode 100644 index 00000000..d6ce3246 --- /dev/null +++ b/src/Api/Struct/Certificate/Info.php @@ -0,0 +1,38 @@ +initScalarProperties($input, [ + ['csr' => 'request'], + ['pvt' => 'privateKey'], + ]); + } else { + foreach ($input as $name => $value) { + $this->$name = $value; + } + } + } + + public function getMapping(): array + { + return array_filter([ + 'csr' => $this->request, + 'pvt' => $this->privateKey, + 'cert' => $this->publicKey, + 'ca' => $this->publicKeyCA, + ]); + } +} diff --git a/src/Api/Struct/Customer/GeneralInfo.php b/src/Api/Struct/Customer/GeneralInfo.php new file mode 100644 index 00000000..755715e0 --- /dev/null +++ b/src/Api/Struct/Customer/GeneralInfo.php @@ -0,0 +1,48 @@ +initScalarProperties($apiResponse, [ + ['cname' => 'company'], + ['pname' => 'personalName'], + 'login', + 'guid', + 'email', + 'phone', + 'fax', + 'address', + ['pcode' => 'postalCode'], + 'city', + 'state', + 'country', + 'external-id', + 'description', + ]); + + $this->enabled = '0' === (string) $apiResponse->status; + } +} diff --git a/src/Api/Struct/Customer/Info.php b/src/Api/Struct/Customer/Info.php new file mode 100644 index 00000000..1b4d4f51 --- /dev/null +++ b/src/Api/Struct/Customer/Info.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'id', + 'guid', + ]); + } +} diff --git a/src/Api/Struct/Database/Info.php b/src/Api/Struct/Database/Info.php new file mode 100644 index 00000000..61c2ab45 --- /dev/null +++ b/src/Api/Struct/Database/Info.php @@ -0,0 +1,28 @@ +initScalarProperties($apiResponse, [ + 'id', + 'name', + 'type', + 'webspace-id', + 'db-server-id', + 'default-user-id', + ]); + } +} diff --git a/src/Api/Struct/Database/UserInfo.php b/src/Api/Struct/Database/UserInfo.php new file mode 100644 index 00000000..2e1f2c54 --- /dev/null +++ b/src/Api/Struct/Database/UserInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'id', + 'login', + 'db-id', + ]); + } +} diff --git a/src/Api/Struct/DatabaseServer/Info.php b/src/Api/Struct/DatabaseServer/Info.php new file mode 100644 index 00000000..678e1afa --- /dev/null +++ b/src/Api/Struct/DatabaseServer/Info.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'id', + 'host', + 'port', + 'type', + ]); + } +} diff --git a/src/Api/Struct/Dns/Info.php b/src/Api/Struct/Dns/Info.php new file mode 100644 index 00000000..e11bb08b --- /dev/null +++ b/src/Api/Struct/Dns/Info.php @@ -0,0 +1,30 @@ +initScalarProperties($apiResponse, [ + 'id', + 'site-id', + 'site-alias-id', + 'type', + 'host', + 'value', + 'opt', + ]); + } +} diff --git a/src/Api/Struct/EventLog/DetailedEvent.php b/src/Api/Struct/EventLog/DetailedEvent.php new file mode 100644 index 00000000..3577d358 --- /dev/null +++ b/src/Api/Struct/EventLog/DetailedEvent.php @@ -0,0 +1,30 @@ +initScalarProperties($apiResponse, [ + 'id', + 'type', + 'time', + 'class', + ['obj_id' => 'objectId'], + 'user', + 'host', + ]); + } +} diff --git a/src/Api/Struct/EventLog/Event.php b/src/Api/Struct/EventLog/Event.php new file mode 100644 index 00000000..86a4bdb6 --- /dev/null +++ b/src/Api/Struct/EventLog/Event.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'type', + 'time', + 'class', + 'id', + ]); + } +} diff --git a/src/Api/Struct/Ip/Info.php b/src/Api/Struct/Ip/Info.php new file mode 100644 index 00000000..12c0996f --- /dev/null +++ b/src/Api/Struct/Ip/Info.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'ip_address', + 'netmask', + 'type', + 'interface', + ]); + } +} diff --git a/src/Api/Struct/Locale/Info.php b/src/Api/Struct/Locale/Info.php new file mode 100644 index 00000000..addd2c4e --- /dev/null +++ b/src/Api/Struct/Locale/Info.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'id', + ['lang' => 'language'], + 'country', + ]); + } +} diff --git a/src/Api/Struct/Mail/GeneralInfo.php b/src/Api/Struct/Mail/GeneralInfo.php new file mode 100644 index 00000000..e2309ed3 --- /dev/null +++ b/src/Api/Struct/Mail/GeneralInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'id', + 'name', + 'description', + ]); + } +} diff --git a/src/Api/Struct/Mail/Info.php b/src/Api/Struct/Mail/Info.php new file mode 100644 index 00000000..552cf89a --- /dev/null +++ b/src/Api/Struct/Mail/Info.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'id', + 'name', + ]); + } +} diff --git a/src/Api/Struct/PhpHandler/Info.php b/src/Api/Struct/PhpHandler/Info.php new file mode 100644 index 00000000..99e20c51 --- /dev/null +++ b/src/Api/Struct/PhpHandler/Info.php @@ -0,0 +1,36 @@ +initScalarProperties($apiResponse, [ + 'id', + 'display-name', + 'full-version', + 'version', + 'type', + 'path', + 'clipath', + 'phpini', + 'custom', + 'handler-status', + ]); + } +} diff --git a/src/Api/Struct/ProtectedDirectory/DataInfo.php b/src/Api/Struct/ProtectedDirectory/DataInfo.php new file mode 100644 index 00000000..b5004beb --- /dev/null +++ b/src/Api/Struct/ProtectedDirectory/DataInfo.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'name', + 'header', + ]); + } +} diff --git a/src/Api/Struct/ProtectedDirectory/Info.php b/src/Api/Struct/ProtectedDirectory/Info.php new file mode 100644 index 00000000..00946111 --- /dev/null +++ b/src/Api/Struct/ProtectedDirectory/Info.php @@ -0,0 +1,18 @@ +initScalarProperties($apiResponse, [ + 'id', + ]); + } +} diff --git a/src/Api/Struct/ProtectedDirectory/UserInfo.php b/src/Api/Struct/ProtectedDirectory/UserInfo.php new file mode 100644 index 00000000..11953da1 --- /dev/null +++ b/src/Api/Struct/ProtectedDirectory/UserInfo.php @@ -0,0 +1,18 @@ +initScalarProperties($apiResponse, [ + 'id', + ]); + } +} diff --git a/src/Api/Struct/Reseller/GeneralInfo.php b/src/Api/Struct/Reseller/GeneralInfo.php new file mode 100644 index 00000000..bf94d328 --- /dev/null +++ b/src/Api/Struct/Reseller/GeneralInfo.php @@ -0,0 +1,29 @@ +{'gen-info'})) { + $this->initScalarProperties($apiResponse->{'gen-info'}, [ + ['pname' => 'personalName'], + 'login', + ]); + } + + $this->permissions = []; + foreach ($apiResponse->permissions->permission ?? [] as $permissionInfo) { + $this->permissions[(string) $permissionInfo->name] = (string) $permissionInfo->value; + } + } +} diff --git a/src/Api/Struct/Reseller/Info.php b/src/Api/Struct/Reseller/Info.php new file mode 100644 index 00000000..e17739bd --- /dev/null +++ b/src/Api/Struct/Reseller/Info.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'id', + 'guid', + ]); + } +} diff --git a/src/Api/Struct/SecretKey/Info.php b/src/Api/Struct/SecretKey/Info.php new file mode 100644 index 00000000..f8fd6b34 --- /dev/null +++ b/src/Api/Struct/SecretKey/Info.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'key', + 'ip_address', + 'description', + 'login', + ]); + } +} diff --git a/src/Api/Struct/Server/Admin.php b/src/Api/Struct/Server/Admin.php new file mode 100644 index 00000000..2e9852ff --- /dev/null +++ b/src/Api/Struct/Server/Admin.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + ['admin_cname' => 'companyName'], + ['admin_pname' => 'name'], + ['admin_email' => 'email'], + ]); + } +} diff --git a/src/Api/Struct/Server/GeneralInfo.php b/src/Api/Struct/Server/GeneralInfo.php new file mode 100644 index 00000000..4fbf87f1 --- /dev/null +++ b/src/Api/Struct/Server/GeneralInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'server_name', + 'server_guid', + 'mode', + ]); + } +} diff --git a/src/Api/Struct/Server/Preferences.php b/src/Api/Struct/Server/Preferences.php new file mode 100644 index 00000000..894bc62d --- /dev/null +++ b/src/Api/Struct/Server/Preferences.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'stat_ttl', + 'traffic_accounting', + 'restart_apache_interval', + ]); + } +} diff --git a/src/Api/Struct/Server/SessionPreferences.php b/src/Api/Struct/Server/SessionPreferences.php new file mode 100644 index 00000000..6acf0562 --- /dev/null +++ b/src/Api/Struct/Server/SessionPreferences.php @@ -0,0 +1,18 @@ +initScalarProperties($apiResponse, [ + 'login_timeout', + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics.php b/src/Api/Struct/Server/Statistics.php new file mode 100644 index 00000000..0bb7063e --- /dev/null +++ b/src/Api/Struct/Server/Statistics.php @@ -0,0 +1,49 @@ +objects = new Statistics\Objects($apiResponse->objects); + $this->version = new Statistics\Version($apiResponse->version); + $this->other = new Statistics\Other($apiResponse->other); + $this->loadAverage = new Statistics\LoadAverage($apiResponse->load_avg); + $this->memory = new Statistics\Memory($apiResponse->mem); + $this->swap = new Statistics\Swap($apiResponse->swap); + + $this->diskSpace = []; + foreach ($apiResponse->diskspace ?? [] as $disk) { + $this->diskSpace[(string) $disk->device->name] = new Statistics\DiskSpace($disk->device); + } + } +} diff --git a/src/Api/Struct/Server/Statistics/DiskSpace.php b/src/Api/Struct/Server/Statistics/DiskSpace.php new file mode 100644 index 00000000..01a96058 --- /dev/null +++ b/src/Api/Struct/Server/Statistics/DiskSpace.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'total', + 'used', + 'free', + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics/LoadAverage.php b/src/Api/Struct/Server/Statistics/LoadAverage.php new file mode 100644 index 00000000..775d7152 --- /dev/null +++ b/src/Api/Struct/Server/Statistics/LoadAverage.php @@ -0,0 +1,20 @@ +load1min = (float) $apiResponse->l1 / 100.0; + $this->load5min = (float) $apiResponse->l5 / 100.0; + $this->load15min = (float) $apiResponse->l15 / 100.0; + } +} diff --git a/src/Api/Struct/Server/Statistics/Memory.php b/src/Api/Struct/Server/Statistics/Memory.php new file mode 100644 index 00000000..fcd18848 --- /dev/null +++ b/src/Api/Struct/Server/Statistics/Memory.php @@ -0,0 +1,28 @@ +initScalarProperties($apiResponse, [ + 'total', + 'used', + 'free', + 'shared', + 'buffer', + 'cached', + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics/Objects.php b/src/Api/Struct/Server/Statistics/Objects.php new file mode 100644 index 00000000..0487ed28 --- /dev/null +++ b/src/Api/Struct/Server/Statistics/Objects.php @@ -0,0 +1,38 @@ +initScalarProperties($apiResponse, [ + 'clients', + 'domains', + 'databases', + ['active_domains' => 'activeDomains'], + ['mail_boxes' => 'mailBoxes'], + ['mail_redirects' => 'mailRedirects'], + ['mail_groups' => 'mailGroups'], + ['mail_responders' => 'mailResponders'], + ['database_users' => 'databaseUsers'], + ['problem_clients' => 'problemClients'], + ['problem_domains' => 'problemDomains'], + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics/Other.php b/src/Api/Struct/Server/Statistics/Other.php new file mode 100644 index 00000000..fd3a576c --- /dev/null +++ b/src/Api/Struct/Server/Statistics/Other.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'cpu', + 'uptime', + ['inside_vz' => 'insideVz'], + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics/Swap.php b/src/Api/Struct/Server/Statistics/Swap.php new file mode 100644 index 00000000..5193fb0e --- /dev/null +++ b/src/Api/Struct/Server/Statistics/Swap.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'total', + 'used', + 'free', + ]); + } +} diff --git a/src/Api/Struct/Server/Statistics/Version.php b/src/Api/Struct/Server/Statistics/Version.php new file mode 100644 index 00000000..58af4bdb --- /dev/null +++ b/src/Api/Struct/Server/Statistics/Version.php @@ -0,0 +1,28 @@ +initScalarProperties($apiResponse, [ + ['plesk_name' => 'internalName'], + ['plesk_version' => 'version'], + ['plesk_build' => 'build'], + ['plesk_os' => 'osName'], + ['plesk_os_version' => 'osVersion'], + ['os_release' => 'osRelease'], + ]); + } +} diff --git a/src/Api/Struct/Server/UpdatesInfo.php b/src/Api/Struct/Server/UpdatesInfo.php new file mode 100644 index 00000000..cb888d48 --- /dev/null +++ b/src/Api/Struct/Server/UpdatesInfo.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'last_installed_update', + 'install_updates_automatically', + ]); + } +} diff --git a/src/Api/Struct/ServicePlan/Info.php b/src/Api/Struct/ServicePlan/Info.php new file mode 100644 index 00000000..62be1bb9 --- /dev/null +++ b/src/Api/Struct/ServicePlan/Info.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'id', + 'name', + 'guid', + 'external-id', + ]); + } +} diff --git a/src/Api/Struct/ServicePlanAddon/Info.php b/src/Api/Struct/ServicePlanAddon/Info.php new file mode 100644 index 00000000..047674f5 --- /dev/null +++ b/src/Api/Struct/ServicePlanAddon/Info.php @@ -0,0 +1,24 @@ +initScalarProperties($apiResponse, [ + 'id', + 'name', + 'guid', + 'external-id', + ]); + } +} diff --git a/src/Api/Struct/Session/Info.php b/src/Api/Struct/Session/Info.php new file mode 100644 index 00000000..d4aba306 --- /dev/null +++ b/src/Api/Struct/Session/Info.php @@ -0,0 +1,28 @@ +initScalarProperties($apiResponse, [ + 'id', + 'type', + 'ip-address', + 'login', + 'login-time', + 'idle', + ]); + } +} diff --git a/src/Api/Struct/Site/GeneralInfo.php b/src/Api/Struct/Site/GeneralInfo.php new file mode 100644 index 00000000..44082a06 --- /dev/null +++ b/src/Api/Struct/Site/GeneralInfo.php @@ -0,0 +1,40 @@ +initScalarProperties($apiResponse, [ + ['cr_date' => 'creationDate'], + 'name', + 'ascii-name', + 'status', + 'real_size', + 'guid', + 'description', + 'webspace-guid', + 'webspace-id', + ]); + + foreach ($apiResponse->dns_ip_address ?? [] as $ip) { + $this->ipAddresses[] = (string) $ip; + } + } +} diff --git a/src/Api/Struct/Site/HostingInfo.php b/src/Api/Struct/Site/HostingInfo.php new file mode 100644 index 00000000..a236c8f6 --- /dev/null +++ b/src/Api/Struct/Site/HostingInfo.php @@ -0,0 +1,25 @@ +vrt_hst->property ?? [] as $property) { + $this->properties[(string) $property->name] = (string) $property->value; + } + + if (!is_null($apiResponse->vrt_hst)) { + $this->initScalarProperties($apiResponse->vrt_hst, [ + 'ip_address', + ]); + } + } +} diff --git a/src/Api/Struct/Site/Info.php b/src/Api/Struct/Site/Info.php new file mode 100644 index 00000000..4d663d03 --- /dev/null +++ b/src/Api/Struct/Site/Info.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'id', + 'guid', + ]); + } +} diff --git a/src/Api/Struct/SiteAlias/GeneralInfo.php b/src/Api/Struct/SiteAlias/GeneralInfo.php new file mode 100644 index 00000000..65951b30 --- /dev/null +++ b/src/Api/Struct/SiteAlias/GeneralInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'name', + 'ascii-name', + 'status', + ]); + } +} diff --git a/src/Api/Struct/SiteAlias/Info.php b/src/Api/Struct/SiteAlias/Info.php new file mode 100644 index 00000000..ae9c82e7 --- /dev/null +++ b/src/Api/Struct/SiteAlias/Info.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'id', + 'status', + ]); + } +} diff --git a/src/Api/Struct/Subdomain/Info.php b/src/Api/Struct/Subdomain/Info.php new file mode 100644 index 00000000..5218d352 --- /dev/null +++ b/src/Api/Struct/Subdomain/Info.php @@ -0,0 +1,27 @@ +properties = []; + $this->initScalarProperties($apiResponse, [ + 'id', + 'parent', + 'name', + ]); + foreach ($apiResponse->property ?? [] as $propertyInfo) { + $this->properties[(string) $propertyInfo->name] = (string) $propertyInfo->value; + } + } +} diff --git a/src/Api/Struct/Ui/CustomButton.php b/src/Api/Struct/Ui/CustomButton.php new file mode 100644 index 00000000..4130a79e --- /dev/null +++ b/src/Api/Struct/Ui/CustomButton.php @@ -0,0 +1,35 @@ +initScalarProperties($apiResponse, ['id']); + + if (!is_null($apiResponse->properties)) { + $this->initScalarProperties($apiResponse->properties, [ + 'sort_key', + 'public', + 'internal', + ['noframe' => 'noFrame'], + 'place', + 'url', + 'text', + ]); + } + } +} diff --git a/src/Api/Struct/Webspace/DiskUsage.php b/src/Api/Struct/Webspace/DiskUsage.php new file mode 100644 index 00000000..e9f44a00 --- /dev/null +++ b/src/Api/Struct/Webspace/DiskUsage.php @@ -0,0 +1,38 @@ +initScalarProperties($apiResponse, [ + 'httpdocs', + 'httpsdocs', + 'subdomains', + 'anonftp', + 'logs', + 'dbases', + 'mailboxes', + 'maillists', + 'domaindumps', + 'configs', + 'chroot', + ]); + } +} diff --git a/src/Api/Struct/Webspace/GeneralInfo.php b/src/Api/Struct/Webspace/GeneralInfo.php new file mode 100644 index 00000000..f2315684 --- /dev/null +++ b/src/Api/Struct/Webspace/GeneralInfo.php @@ -0,0 +1,45 @@ +initScalarProperties($apiResponse, [ + ['cr_date' => 'creationDate'], + 'name', + 'ascii-name', + 'status', + 'real_size', + 'owner-id', + 'guid', + 'vendor-guid', + 'description', + 'admin-description', + ]); + + foreach ($apiResponse->dns_ip_address ?? [] as $ip) { + $this->ipAddresses[] = (string) $ip; + } + + $this->enabled = '0' === (string) $apiResponse->status; + } +} diff --git a/src/Api/Struct/Webspace/HostingPropertyInfo.php b/src/Api/Struct/Webspace/HostingPropertyInfo.php new file mode 100644 index 00000000..4e0f8c45 --- /dev/null +++ b/src/Api/Struct/Webspace/HostingPropertyInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'name', + 'type', + 'label', + ]); + } +} diff --git a/src/Api/Struct/Webspace/Info.php b/src/Api/Struct/Webspace/Info.php new file mode 100644 index 00000000..702d1cf2 --- /dev/null +++ b/src/Api/Struct/Webspace/Info.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'id', + 'guid', + ]); + $this->name = $name; + } +} diff --git a/src/Api/Struct/Webspace/Limit.php b/src/Api/Struct/Webspace/Limit.php new file mode 100644 index 00000000..290b7e67 --- /dev/null +++ b/src/Api/Struct/Webspace/Limit.php @@ -0,0 +1,20 @@ +initScalarProperties($apiResponse, [ + 'name', + 'value', + ]); + } +} diff --git a/src/Api/Struct/Webspace/LimitDescriptor.php b/src/Api/Struct/Webspace/LimitDescriptor.php new file mode 100644 index 00000000..2114621b --- /dev/null +++ b/src/Api/Struct/Webspace/LimitDescriptor.php @@ -0,0 +1,20 @@ +limits = []; + + foreach ($apiResponse->descriptor->property ?? [] as $propertyInfo) { + $this->limits[(string) $propertyInfo->name] = new LimitInfo($propertyInfo); + } + } +} diff --git a/src/Api/Struct/Webspace/LimitInfo.php b/src/Api/Struct/Webspace/LimitInfo.php new file mode 100644 index 00000000..b7f0262f --- /dev/null +++ b/src/Api/Struct/Webspace/LimitInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'name', + 'type', + 'label', + ]); + } +} diff --git a/src/Api/Struct/Webspace/Limits.php b/src/Api/Struct/Webspace/Limits.php new file mode 100644 index 00000000..63622a2d --- /dev/null +++ b/src/Api/Struct/Webspace/Limits.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, ['overuse']); + $this->limits = []; + + foreach ($apiResponse->limit ?? [] as $limit) { + $this->limits[(string) $limit->name] = new Limit($limit); + } + } +} diff --git a/src/Api/Struct/Webspace/PermissionDescriptor.php b/src/Api/Struct/Webspace/PermissionDescriptor.php new file mode 100644 index 00000000..929f3e05 --- /dev/null +++ b/src/Api/Struct/Webspace/PermissionDescriptor.php @@ -0,0 +1,20 @@ +permissions = []; + + foreach ($apiResponse->descriptor->property ?? [] as $propertyInfo) { + $this->permissions[(string) $propertyInfo->name] = new PermissionInfo($propertyInfo); + } + } +} diff --git a/src/Api/Struct/Webspace/PermissionInfo.php b/src/Api/Struct/Webspace/PermissionInfo.php new file mode 100644 index 00000000..2328222a --- /dev/null +++ b/src/Api/Struct/Webspace/PermissionInfo.php @@ -0,0 +1,22 @@ +initScalarProperties($apiResponse, [ + 'name', + 'type', + 'label', + ]); + } +} diff --git a/src/Api/Struct/Webspace/PhpSettings.php b/src/Api/Struct/Webspace/PhpSettings.php new file mode 100644 index 00000000..1ddf88d9 --- /dev/null +++ b/src/Api/Struct/Webspace/PhpSettings.php @@ -0,0 +1,20 @@ +properties = []; + + foreach ($apiResponse->webspace->get->result->data->{'php-settings'}->setting ?? [] as $setting) { + $this->properties[(string) $setting->name] = (string) $setting->value; + } + } +} diff --git a/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php b/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php new file mode 100644 index 00000000..cac2b792 --- /dev/null +++ b/src/Api/Struct/Webspace/PhysicalHostingDescriptor.php @@ -0,0 +1,20 @@ +properties = []; + + foreach ($apiResponse->descriptor->property ?? [] as $propertyInfo) { + $this->properties[(string) $propertyInfo->name] = new HostingPropertyInfo($propertyInfo); + } + } +} diff --git a/src/Api/XmlResponse.php b/src/Api/XmlResponse.php new file mode 100644 index 00000000..dd22cf08 --- /dev/null +++ b/src/Api/XmlResponse.php @@ -0,0 +1,27 @@ +xpath('//' . $node); + if (is_array($result) && isset($result[0])) { + return (string) $result[0]; + } + + return ''; + } +} diff --git a/src/PleskX/Api/Client.php b/src/PleskX/Api/Client.php deleted file mode 100644 index e98929c9..00000000 --- a/src/PleskX/Api/Client.php +++ /dev/null @@ -1,581 +0,0 @@ -_host = $host; - $this->_port = $port; - $this->_protocol = $protocol; - } - - /** - * Setup credentials for authentication - * - * @param string $login - * @param string $password - */ - public function setCredentials($login, $password) - { - $this->_login = $login; - $this->_password = $password; - } - - /** - * Define secret key for alternative authentication - * - * @param string $secretKey - */ - public function setSecretKey($secretKey) - { - $this->_secretKey = $secretKey; - } - - /** - * Set default version for requests - * - * @param string $version - */ - public function setVersion($version) - { - $this->_version = $version; - } - - /** - * Set custom function to verify response of API call according your own needs. Default verifying will be used if it is not specified - * - * @param callable|null $function - */ - public function setVerifyResponse(callable $function = null) - { - $this->_verifyResponseCallback = $function; - } - - /** - * Retrieve host used for communication - * - * @return string - */ - public function getHost() - { - return $this->_host; - } - - /** - * Retrieve port used for communication - * - * @return int - */ - public function getPort() - { - return $this->_port; - } - - /** - * Retrieve name of the protocol (http or https) used for communication - * - * @return string - */ - public function getProtocol() - { - return $this->_protocol; - } - - /** - * Retrieve XML template for packet - * - * @param string|null $version - * @return SimpleXMLElement - */ - public function getPacket($version = null) - { - $protocolVersion = !is_null($version) ? $version : $this->_version; - $content = ""; - $content .= ""; - return new SimpleXMLElement($content); - } - - /** - * Perform API request - * - * @param string|array|SimpleXMLElement $request - * @param int $mode - * @return XmlResponse - */ - public function request($request, $mode = self::RESPONSE_SHORT) - { - if ($request instanceof SimpleXMLElement) { - $request = $request->asXml(); - } else { - $xml = $this->getPacket(); - - if (is_array($request)) { - $request = $this->_arrayToXml($request, $xml)->asXML(); - } else if (preg_match('/^[a-z]/', $request)) { - $request = $this->_expandRequestShortSyntax($request, $xml); - } - } - - if ('sdk' == $this->_protocol) { - $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); - } - - $this->_verifyResponseCallback - ? call_user_func($this->_verifyResponseCallback, $xml) - : $this->_verifyResponse($xml); - - return (self::RESPONSE_FULL == $mode) ? $xml : $xml->xpath('//result')[0]; - } - - /** - * Perform HTTP request to end-point - * - * @param string $request - * @return XmlResponse - * @throws Client\Exception - */ - private function _performHttpRequest($request) - { - $curl = curl_init(); - - curl_setopt($curl, CURLOPT_URL, "$this->_protocol://$this->_host:$this->_port/enterprise/control/agent.php"); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); - curl_setopt($curl, CURLOPT_HTTPHEADER, $this->_getHeaders()); - curl_setopt($curl, CURLOPT_POSTFIELDS, $request); - - $result = curl_exec($curl); - - if (false === $result) { - throw new Client\Exception(curl_error($curl), curl_errno($curl)); - } - - if (self::$_isExecutionsLogEnabled) { - self::$_executionLog[] = [ - 'trace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), - 'request' => $request, - 'response' => $result, - ]; - } - - curl_close($curl); - - $xml = new XmlResponse($result); - return $xml; - } - - /** - * Perform multiple API requests using single HTTP request - * - * @param $requests - * @param int $mode - * @return array - * @throws Client\Exception - */ - public function multiRequest($requests, $mode = self::RESPONSE_SHORT) - { - - $requestXml = $this->getPacket(); - - 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(); - } else if (preg_match('/^[a-z]/', $request)) { - $this->_expandRequestShortSyntax($request, $requestXml); - } - } - $responses[] = $this->request($request); - } - - if ('sdk' == $this->_protocol) { - throw new Client\Exception('Multi requests are not supported via SDK.'); - } else { - $responseXml = $this->_performHttpRequest($requestXml->asXML()); - } - - $responses = []; - foreach ($responseXml->children() as $childNode) { - $xml = $this->getPacket(); - $dom = dom_import_simplexml($xml)->ownerDocument; - - $childDomNode = dom_import_simplexml($childNode); - $childDomNode = $dom->importNode($childDomNode, true); - $dom->documentElement->appendChild($childDomNode); - - $response = simplexml_load_string($dom->saveXML()); - $responses[] = (self::RESPONSE_FULL == $mode) ? $response : $response->xpath('//result')[0]; - } - - return $responses; - } - - /** - * Retrieve list of headers needed for request - * - * @return array - */ - protected function _getHeaders() - { - $headers = array( - "Content-Type: text/xml", - "HTTP_PRETTY_PRINT: TRUE", - ); - - if ($this->_secretKey) { - $headers[] = "KEY: $this->_secretKey"; - } else { - $headers[] = "HTTP_AUTH_LOGIN: $this->_login"; - $headers[] = "HTTP_AUTH_PASSWD: $this->_password"; - } - - return $headers; - } - - /** - * Enable or disable execution log - * - * @param bool $enable - */ - public static function enableExecutionLog($enable = true) - { - self::$_isExecutionsLogEnabled = $enable; - } - - /** - * Retrieve execution log - * - * @return array - */ - public static function getExecutionLog() - { - return self::$_executionLog; - } - - /** - * Verify that response does not contain errors - * - * @param XmlResponse $xml - * @throws Exception - */ - 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->xpath('//status[text()="error"]') && $xml->xpath('//errcode') && $xml->xpath('//errtext')) { - $errorCode = (int)$xml->xpath('//errcode')[0]; - $errorMessage = (string)$xml->xpath('//errtext')[0]; - throw new Exception($errorMessage, $errorCode); - } - } - - /** - * Expand short syntax (some.method.call) into full XML representation - * - * @param string $request - * @param SimpleXMLElement $xml - * @return string - */ - protected function _expandRequestShortSyntax($request, SimpleXMLElement $xml) - { - $parts = explode('.', $request); - $node = $xml; - - foreach ($parts as $part) { - @list($name, $value) = explode('=', $part); - $node = $node->addChild($name, $value); - } - - return $xml->asXML(); - } - - /** - * Convert array to XML representation - * - * @param array $array - * @param SimpleXMLElement $xml - * @param string $parentEl - * @return SimpleXMLElement - */ - protected function _arrayToXml(array $array, SimpleXMLElement $xml, $parentEl = null) - { - foreach ($array as $key => $value) { - $el = is_int($key) && $parentEl ? $parentEl : $key; - if (is_array($value)) { - $this->_arrayToXml($value, $this->_isAssocArray($value) ? $xml->addChild($el) : $xml, $el); - } else { - $xml->addChild($el, $value); - } - } - - return $xml; - } - - /** - * @param array $array - * @return bool - */ - protected function _isAssocArray(array $array) - { - return $array && array_keys($array) !== range(0, count($array) - 1); - } - - /** - * @param string $name - * @return \PleskX\Api\Operator - */ - protected function _getOperator($name) - { - if (!isset($this->_operatorsCache[$name])) { - $className = '\\PleskX\\Api\\Operator\\' . $name; - $this->_operatorsCache[$name] = new $className($this); - } - - return $this->_operatorsCache[$name]; - } - - /** - * @return Operator\Server - */ - public function server() - { - return $this->_getOperator('Server'); - } - - /** - * @return Operator\Customer - */ - public function customer() - { - return $this->_getOperator('Customer'); - } - - /** - * @return Operator\Webspace - */ - public function webspace() - { - return $this->_getOperator('Webspace'); - } - - /** - * @return Operator\Subdomain - */ - public function subdomain() - { - return $this->_getOperator('Subdomain'); - } - - /** - * @return Operator\Dns - */ - public function dns() - { - return $this->_getOperator('Dns'); - } - - /** - * @return Operator\DatabaseServer - */ - public function databaseServer() - { - return $this->_getOperator('DatabaseServer'); - } - - /** - * @return Operator\Mail - */ - public function mail() - { - return $this->_getOperator('Mail'); - } - - /** - * @return Operator\Certificate - */ - public function certificate() - { - return $this->_getOperator('Certificate'); - } - - /** - * @return Operator\SiteAlias - */ - public function siteAlias() - { - return $this->_getOperator('SiteAlias'); - } - - /** - * @return Operator\Ip - */ - public function ip() - { - return $this->_getOperator('Ip'); - } - - /** - * @return Operator\EventLog - */ - public function eventLog() - { - return $this->_getOperator('EventLog'); - } - - /** - * @return Operator\SecretKey - */ - public function secretKey() - { - return $this->_getOperator('SecretKey'); - } - - /** - * @return Operator\Ui - */ - public function ui() - { - return $this->_getOperator('Ui'); - } - - /** - * @return Operator\ServicePlan - */ - public function servicePlan() - { - return $this->_getOperator('ServicePlan'); - } - - /** - * @return Operator\VirtualDirectory - */ - public function virtualDirectory() - { - return $this->_getOperator('VirtualDirectory'); - } - - /** - * @return Operator\Database - */ - public function database() - { - return $this->_getOperator('Database'); - } - - /** - * @return Operator\Session - */ - public function session() - { - return $this->_getOperator('Session'); - } - - /** - * @return Operator\Locale - */ - public function locale() - { - return $this->_getOperator('Locale'); - } - - /** - * @return Operator\LogRotation - */ - public function logRotation() - { - return $this->_getOperator('LogRotation'); - } - - /** - * @return Operator\ProtectedDirectory - */ - public function protectedDirectory() - { - return $this->_getOperator('ProtectedDirectory'); - } - - /** - * @return Operator\Reseller - */ - public function reseller() - { - return $this->_getOperator('Reseller'); - } - - /** - * @return Operator\ResellerPlan - */ - public function resellerPlan() - { - return $this->_getOperator('ResellerPlan'); - } - - /** - * @return Operator\Aps - */ - public function aps() - { - return $this->_getOperator('Aps'); - } - - /** - * @return Operator\ServicePlanAddon - */ - public function servicePlanAddon() - { - return $this->_getOperator('ServicePlanAddon'); - } - - /** - * @return Operator\Site - */ - public function site() - { - return $this->_getOperator('Site'); - } -} diff --git a/src/PleskX/Api/Client/Exception.php b/src/PleskX/Api/Client/Exception.php deleted file mode 100644 index 0a3d27de..00000000 --- a/src/PleskX/Api/Client/Exception.php +++ /dev/null @@ -1,11 +0,0 @@ -_login = $login; - } -} diff --git a/src/PleskX/Api/Operator.php b/src/PleskX/Api/Operator.php deleted file mode 100755 index c4880e8b..00000000 --- a/src/PleskX/Api/Operator.php +++ /dev/null @@ -1,93 +0,0 @@ -_client = $client; - - if (is_null($this->_wrapperTag)) { - $classNameParts = explode('\\', get_class($this)); - $this->_wrapperTag = end($classNameParts); - $this->_wrapperTag = strtolower(preg_replace('/([a-z])([A-Z])/', '\1-\2', $this->_wrapperTag)); - } - } - - /** - * Perform plain API request - * - * @param string|array $request - * @param int $mode - * @return XmlResponse - */ - public function request($request, $mode = Client::RESPONSE_SHORT) - { - $wrapperTag = $this->_wrapperTag; - - if (is_array($request)) { - $request = [$wrapperTag => $request]; - } else if (preg_match('/^[a-z]/', $request)) { - $request = "$wrapperTag.$request"; - } else { - $request = "<$wrapperTag>$request"; - } - - return $this->_client->request($request, $mode); - } - - /** - * @param string $field - * @param integer|string $value - * @param string $deleteMethodName - * @return bool - */ - protected function _delete($field, $value, $deleteMethodName = 'del') - { - $response = $this->request("$deleteMethodName.filter.$field=$value"); - return 'ok' === (string)$response->status; - } - - /** - * @param string $structClass - * @param string $infoTag - * @param string|null $field - * @param integer|string|null $value - * @param callable|null $filter - * @return mixed - */ - protected function _getItems($structClass, $infoTag, $field = null, $value = null, callable $filter = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $getTag->addChild('dataset')->addChild($infoTag); - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - if (!is_null($filter) && !$filter($xmlResult->data->$infoTag)) { - continue; - } - $items[] = new $structClass($xmlResult->data->$infoTag); - } - - return $items; - } - -} diff --git a/src/PleskX/Api/Operator/Certificate.php b/src/PleskX/Api/Operator/Certificate.php deleted file mode 100644 index 1284662e..00000000 --- a/src/PleskX/Api/Operator/Certificate.php +++ /dev/null @@ -1,27 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('generate')->addChild('info'); - - foreach ($properties as $name => $value) { - $info->addChild($name, $value); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - -} diff --git a/src/PleskX/Api/Operator/Customer.php b/src/PleskX/Api/Operator/Customer.php deleted file mode 100644 index 16824539..00000000 --- a/src/PleskX/Api/Operator/Customer.php +++ /dev/null @@ -1,56 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add')->addChild('gen_info'); - - foreach ($properties as $name => $value) { - $info->addChild($name, $value); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\GeneralInfo - */ - public function get($field, $value) - { - $items = $this->_getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); - return reset($items); - } - - /** - * @return Struct\GeneralInfo[] - */ - public function getAll() - { - return $this->_getItems(Struct\GeneralInfo::class, 'gen_info'); - } - -} diff --git a/src/PleskX/Api/Operator/Database.php b/src/PleskX/Api/Operator/Database.php deleted file mode 100644 index 70e8a338..00000000 --- a/src/PleskX/Api/Operator/Database.php +++ /dev/null @@ -1,149 +0,0 @@ -_process('add-db', $properties)); - } - - /** - * @param $properties - * @return Struct\UserInfo - */ - public function createUser($properties) - { - return new Struct\UserInfo($this->_process('add-db-user', $properties)); - } - - /** - * @param $command - * @param array $properties - * @return \PleskX\Api\XmlResponse - */ - private function _process($command, array $properties) - { - $packet = $this->_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild($command); - - foreach ($properties as $name => $value) { - if (false !== strpos($value, '&')) { - $info->$name = $value; - continue; - } - $info->addChild($name, $value); - } - - return $this->_client->request($packet); - } - - /** - * @param array $properties - * @return bool - */ - public function updateUser(array $properties) - { - $response = $this->_process('set-db-user', $properties); - return 'ok' === (string)$response->status; - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info - */ - public function get($field, $value) - { - $items = $this->getAll($field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\UserInfo - */ - public function getUser($field, $value) - { - $items = $this->getAllUsers($field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info[] - */ - public function getAll($field, $value) - { - $response = $this->_get('get-db', $field, $value); - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $items[] = new Struct\Info($xmlResult); - } - return $items; - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\UserInfo[] - */ - public function getAllUsers($field, $value) - { - $response = $this->_get('get-db-users', $field, $value); - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $items[] = new Struct\UserInfo($xmlResult); - } - return $items; - } - - /** - * @param $command - * @param $field - * @param $value - * @return \PleskX\Api\XmlResponse - */ - private function _get($command, $field, $value) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild($command); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - return $response; - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value, 'del-db'); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function deleteUser($field, $value) - { - return $this->_delete($field, $value, 'del-db-user'); - } -} diff --git a/src/PleskX/Api/Operator/DatabaseServer.php b/src/PleskX/Api/Operator/DatabaseServer.php deleted file mode 100644 index 0d186bfa..00000000 --- a/src/PleskX/Api/Operator/DatabaseServer.php +++ /dev/null @@ -1,68 +0,0 @@ -request('get-supported-types'); - return (array)$response->type; - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info - */ - public function get($field, $value) - { - $items = $this->_get($field, $value); - return reset($items); - } - - /** - * @return Struct\Info[] - */ - public function getAll() - { - return $this->_get(); - } - - /** - * @param string|null $field - * @param integer|string|null $value - * @return Struct\Info|Struct\Info[] - */ - private function _get($field = null, $value = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $item = new Struct\Info($xmlResult->data); - $item->id = (int)$xmlResult->id; - $items[] = $item; - } - - return $items; - } - -} diff --git a/src/PleskX/Api/Operator/Dns.php b/src/PleskX/Api/Operator/Dns.php deleted file mode 100644 index d8380b13..00000000 --- a/src/PleskX/Api/Operator/Dns.php +++ /dev/null @@ -1,69 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add_rec'); - - foreach ($properties as $name => $value) { - $info->addChild($name, $value); - } - - return new Struct\Info($this->_client->request($packet)); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info - */ - public function get($field, $value) - { - $items = $this->getAll($field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info[] - */ - public function getAll($field, $value) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get_rec'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $item = new Struct\Info($xmlResult->data); - $item->id = (int)$xmlResult->id; - $items[] = $item; - } - return $items; - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value, 'del_rec'); - } -} diff --git a/src/PleskX/Api/Operator/Ip.php b/src/PleskX/Api/Operator/Ip.php deleted file mode 100644 index 56fe81a7..00000000 --- a/src/PleskX/Api/Operator/Ip.php +++ /dev/null @@ -1,27 +0,0 @@ -_client->getPacket(); - $packet->addChild($this->_wrapperTag)->addChild('get'); - $response = $this->_client->request($packet); - - foreach ($response->addresses->ip_info as $ipInfo) { - $ips[] = new Struct\Info($ipInfo); - } - - return $ips; - } - -} diff --git a/src/PleskX/Api/Operator/Locale.php b/src/PleskX/Api/Operator/Locale.php deleted file mode 100644 index a9f1325d..00000000 --- a/src/PleskX/Api/Operator/Locale.php +++ /dev/null @@ -1,33 +0,0 @@ -_client->getPacket(); - $filter = $packet->addChild($this->_wrapperTag)->addChild('get')->addChild('filter'); - - if (!is_null($id)) { - $filter->addChild('id', $id); - } - - $response = $this->_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); - } - - return !is_null($id) ? reset($locales) : $locales; - } - -} diff --git a/src/PleskX/Api/Operator/Mail.php b/src/PleskX/Api/Operator/Mail.php deleted file mode 100644 index 4a91eef2..00000000 --- a/src/PleskX/Api/Operator/Mail.php +++ /dev/null @@ -1,53 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('create'); - - $filter = $info->addChild('filter'); - $filter->addChild('site-id', $siteId); - $mailname = $filter->addChild('mailname'); - $mailname->addChild('name', $name); - if ($mailbox) { - $mailname->addChild('mailbox')->addChild('enabled', 'true'); - } - if (!empty($password)) { - $mailname->addChild('password')->addChild('value', $password); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response->mailname); - } - - /** - * @param string $field - * @param integer|string $value - * @param integer $siteId - * @return bool - */ - public function delete($field, $value, $siteId) - { - $packet = $this->_client->getPacket(); - $filter = $packet->addChild($this->_wrapperTag)->addChild('remove')->addChild('filter'); - $filter->addChild('site-id', $siteId); - $filter->addChild($field, $value); - $response = $this->_client->request($packet); - return 'ok' === (string)$response->status; - } - -} diff --git a/src/PleskX/Api/Operator/ProtectedDirectory.php b/src/PleskX/Api/Operator/ProtectedDirectory.php deleted file mode 100644 index 537432cf..00000000 --- a/src/PleskX/Api/Operator/ProtectedDirectory.php +++ /dev/null @@ -1,11 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add')->addChild('gen-info'); - - foreach ($properties as $name => $value) { - $info->addChild($name, $value); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value); - } - - - /** - * @param string $field - * @param integer|string $value - * @return Struct\GeneralInfo - */ - public function get($field, $value) - { - $items = $this->getAll($field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\GeneralInfo[] - */ - public function getAll($field = null, $value = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $datasetTag = $getTag->addChild('dataset'); - $datasetTag->addChild('gen-info'); - $datasetTag->addChild('permissions'); - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $item = new Struct\GeneralInfo($xmlResult->data); - $item->id = (int)$xmlResult->id; - $items[] = $item; - } - - return $items; - } - - - -} diff --git a/src/PleskX/Api/Operator/SecretKey.php b/src/PleskX/Api/Operator/SecretKey.php deleted file mode 100644 index 8d3c0f1a..00000000 --- a/src/PleskX/Api/Operator/SecretKey.php +++ /dev/null @@ -1,75 +0,0 @@ -_client->getPacket(); - $packet->addChild($this->_wrapperTag)->addChild('create')->addChild('ip_address', $ipAddress); - $response = $this->_client->request($packet); - return (string)$response->key; - } - - /** - * @param string $keyId - * @return bool - */ - public function delete($keyId) - { - return $this->_delete('key', $keyId, 'delete'); - } - - /** - * @param string $keyId - * @return Struct\Info - */ - public function get($keyId) - { - $items = $this->_get($keyId); - return reset($items); - } - - /** - * @return Struct\Info[] - */ - public function getAll() - { - return $this->_get(); - } - - /** - * @param string|null $keyId - * @return Struct\Info[] - */ - public function _get($keyId = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get_info'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($keyId)) { - $filterTag->addChild('key', $keyId); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result/key_info') as $keyInfo) { - $items[] = new Struct\Info($keyInfo); - } - - return $items; - } - -} diff --git a/src/PleskX/Api/Operator/Server.php b/src/PleskX/Api/Operator/Server.php deleted file mode 100644 index ee560bca..00000000 --- a/src/PleskX/Api/Operator/Server.php +++ /dev/null @@ -1,171 +0,0 @@ -_client->getPacket(); - $packet->addChild($this->_wrapperTag)->addChild('get_protos'); - $response = $this->_client->request($packet); - - return (array)$response->protos->proto; - } - - public function getGeneralInfo() - { - return new Struct\GeneralInfo($this->_getInfo('gen_info')); - } - - public function getPreferences() - { - return new Struct\Preferences($this->_getInfo('prefs')); - } - - public function getAdmin() - { - return new Struct\Admin($this->_getInfo('admin')); - } - - /** - * @return array - */ - public function getKeyInfo() - { - $keyInfo = []; - $keyInfoXml = $this->_getInfo('key'); - - foreach ($keyInfoXml->property as $property) { - $keyInfo[(string)$property->name] = (string)$property->value; - } - - return $keyInfo; - } - - /** - * @return array - */ - public function getComponents() - { - $components = []; - $componentsXml = $this->_getInfo('components'); - - foreach ($componentsXml->component as $component) { - $components[(string)$component->name] = (string)$component->version; - } - - return $components; - } - - /** - * @return array - */ - public function getServiceStates() - { - $states = []; - $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, - ]; - } - - return $states; - } - - public function getSessionPreferences() - { - return new Struct\SessionPreferences($this->_getInfo('session_setup')); - } - - /** - * @return array - */ - public function getShells() - { - $shells = []; - $shellsXml = $this->_getInfo('shells'); - - foreach ($shellsXml->shell as $shell) { - $shells[(string)$shell->name] = (string)$shell->path; - } - - return $shells; - } - - /** - * @return array - */ - public function getNetworkInterfaces() - { - $interfacesXml = $this->_getInfo('interfaces'); - return (array)$interfacesXml->interface; - } - - public function getStatistics() - { - return new Struct\Statistics($this->_getInfo('stat')); - } - - /** - * @return array - */ - public function getSiteIsolationConfig() - { - $config = []; - $configXml = $this->_getInfo('site-isolation-config'); - - foreach ($configXml->property as $property) { - $config[(string)$property->name] = (string)$property->value; - } - - return $config; - } - - public function getUpdatesInfo() - { - return new Struct\UpdatesInfo($this->_getInfo('updates')); - } - - /** - * @param string $login - * @param string $clientIp - * @return string - */ - public function createSession($login, $clientIp) - { - $packet = $this->_client->getPacket(); - $sessionNode = $packet->addChild($this->_wrapperTag)->addChild('create_session'); - $sessionNode->addChild('login', $login); - $dataNode = $sessionNode->addChild('data'); - $dataNode->addChild('user_ip', base64_encode($clientIp)); - $dataNode->addChild('source_server'); - $response = $this->_client->request($packet); - - return (string)$response->id; - } - - /** - * @param string $operation - * @return \SimpleXMLElement - */ - private function _getInfo($operation) - { - $packet = $this->_client->getPacket(); - $packet->addChild($this->_wrapperTag)->addChild('get')->addChild($operation); - $response = $this->_client->request($packet); - - return $response->$operation; - } - -} diff --git a/src/PleskX/Api/Operator/ServicePlan.php b/src/PleskX/Api/Operator/ServicePlan.php deleted file mode 100644 index 13f082f1..00000000 --- a/src/PleskX/Api/Operator/ServicePlan.php +++ /dev/null @@ -1,55 +0,0 @@ -_get($field, $value); - return reset($items); - } - - /** - * @return Struct\Info[] - */ - public function getAll() - { - return $this->_get(); - } - - /** - * @param string|null $field - * @param integer|string|null $value - * @return Struct\Info|Struct\Info[] - */ - private function _get($field = null, $value = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - $items[] = new Struct\Info($xmlResult); - } - - return $items; - } - -} diff --git a/src/PleskX/Api/Operator/ServicePlanAddon.php b/src/PleskX/Api/Operator/ServicePlanAddon.php deleted file mode 100644 index 14979d01..00000000 --- a/src/PleskX/Api/Operator/ServicePlanAddon.php +++ /dev/null @@ -1,9 +0,0 @@ -request('get'); - - foreach ($response->session as $sessionInfo) { - $sessions[(string)$sessionInfo->id] = new Struct\Info($sessionInfo); - } - - return $sessions; - } - - /** - * @param string $sessionId - * @return bool - */ - public function terminate($sessionId) - { - $response = $this->request("terminate.session-id=$sessionId"); - return 'ok' === (string)$response->status; - } - -} diff --git a/src/PleskX/Api/Operator/Site.php b/src/PleskX/Api/Operator/Site.php deleted file mode 100755 index 106110b6..00000000 --- a/src/PleskX/Api/Operator/Site.php +++ /dev/null @@ -1,84 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add'); - - $infoGeneral = $info->addChild('gen_setup'); - foreach ($properties as $name => $value) { - if (!is_scalar($value)) { - continue; - } - $infoGeneral->addChild($name, $value); - } - - // set hosting properties - if (isset($properties[static::PROPERTIES_HOSTING]) && is_array($properties[static::PROPERTIES_HOSTING])) { - $hostingNode = $info->addChild('hosting')->addChild('vrt_hst'); - foreach ($properties[static::PROPERTIES_HOSTING] as $name => $value) { - $propertyNode = $hostingNode->addChild('property'); - $propertyNode->addChild('name', $name); - $propertyNode->addChild('value', $value); - } - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\GeneralInfo - */ - public function get($field, $value) - { - $items = $this->_getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\HostingInfo|null - */ - public function getHosting($field, $value) - { - $items = $this->_getItems(Struct\HostingInfo::class, 'hosting', $field, $value, function ($node) { - return isset($node->vrt_hst); - }); - return empty($items) ? null : reset($items); - } - - /** - * @return Struct\GeneralInfo[] - */ - public function getAll() - { - return $this->_getItems(Struct\GeneralInfo::class, 'gen_info'); - } - -} diff --git a/src/PleskX/Api/Operator/SiteAlias.php b/src/PleskX/Api/Operator/SiteAlias.php deleted file mode 100644 index b465c4ee..00000000 --- a/src/PleskX/Api/Operator/SiteAlias.php +++ /dev/null @@ -1,35 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('create'); - - if (count($preferences) > 0) { - $prefs = $info->addChild('pref'); - - foreach ($preferences as $key => $value) { - $prefs->addChild($key, is_bool($value) ? ($value ? 1 : 0) : $value); - } - } - - $info->addChild('site-id', $properties['site-id']); - $info->addChild('name', $properties['name']); - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - -} diff --git a/src/PleskX/Api/Operator/Subdomain.php b/src/PleskX/Api/Operator/Subdomain.php deleted file mode 100644 index bff91390..00000000 --- a/src/PleskX/Api/Operator/Subdomain.php +++ /dev/null @@ -1,84 +0,0 @@ -_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add'); - - foreach ($properties as $name => $value) { - if (is_array($value)) { - foreach ($value as $propertyName => $propertyValue) { - $property = $info->addChild($name); - $property->addChild('name', $propertyName); - $property->addChild('value', $propertyValue); - } - continue; - } - $info->addChild($name, $value); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info - */ - public function get($field, $value) - { - $items = $this->getAll($field, $value); - return reset($items); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\Info[] - */ - public function getAll($field = null, $value = null) - { - $packet = $this->_client->getPacket(); - $getTag = $packet->addChild($this->_wrapperTag)->addChild('get'); - - $filterTag = $getTag->addChild('filter'); - if (!is_null($field)) { - $filterTag->addChild($field, $value); - } - - $response = $this->_client->request($packet, \PleskX\Api\Client::RESPONSE_FULL); - - $items = []; - foreach ($response->xpath('//result') as $xmlResult) { - if (empty($xmlResult->data)) { - continue; - } - $item = new Struct\Info($xmlResult->data); - $item->id = (int)$xmlResult->id; - $items[] = $item; - } - - return $items; - } -} diff --git a/src/PleskX/Api/Operator/Ui.php b/src/PleskX/Api/Operator/Ui.php deleted file mode 100644 index 06b0ee00..00000000 --- a/src/PleskX/Api/Operator/Ui.php +++ /dev/null @@ -1,58 +0,0 @@ -request('get-navigation'); - return unserialize(base64_decode($response->navigation)); - } - - /** - * @param string $owner - * @param array $properties - * @return int - */ - public function createCustomButton($owner, $properties) - { - $packet = $this->_client->getPacket(); - $buttonNode = $packet->addChild($this->_wrapperTag)->addChild('create-custombutton'); - $buttonNode->addChild('owner')->addChild($owner); - $propertiesNode = $buttonNode->addChild('properties'); - - foreach ($properties as $name => $value) { - $propertiesNode->addChild($name, $value); - } - - $response = $this->_client->request($packet); - return (int)$response->id; - } - - /** - * @param int $id - * @return Struct\CustomButton - */ - public function getCustomButton($id) - { - $response = $this->request("get-custombutton.filter.custombutton-id=$id"); - return new Struct\CustomButton($response); - } - - /** - * @param int $id - * @return bool - */ - public function deleteCustomButton($id) - { - return $this->_delete('custombutton-id', $id, 'delete-custombutton'); - } - -} diff --git a/src/PleskX/Api/Operator/VirtualDirectory.php b/src/PleskX/Api/Operator/VirtualDirectory.php deleted file mode 100644 index 9c1e6c29..00000000 --- a/src/PleskX/Api/Operator/VirtualDirectory.php +++ /dev/null @@ -1,11 +0,0 @@ -request('get-permission-descriptor.filter'); - return new Struct\PermissionDescriptor($response); - } - - public function getLimitDescriptor() - { - $response = $this->request('get-limit-descriptor.filter'); - return new Struct\LimitDescriptor($response); - } - - public function getPhysicalHostingDescriptor() - { - $response = $this->request('get-physical-hosting-descriptor.filter'); - return new Struct\PhysicalHostingDescriptor($response); - } - - /** - * @param array $properties - * @param array|null $hostingProperties - * @param $planName - * @return Struct\Info - */ - public function create(array $properties, array $hostingProperties = null, $planName = null) - { - $packet = $this->_client->getPacket(); - $info = $packet->addChild($this->_wrapperTag)->addChild('add'); - - $infoGeneral = $info->addChild('gen_setup'); - foreach ($properties as $name => $value) { - $infoGeneral->addChild($name, $value); - } - - if ($hostingProperties) { - $infoHosting = $info->addChild('hosting')->addChild('vrt_hst'); - foreach ($hostingProperties as $name => $value) { - $property = $infoHosting->addChild('property'); - $property->addChild('name', $name); - $property->addChild('value', $value); - } - - if (isset($properties['ip_address'])) { - $infoHosting->addChild("ip_address", $properties['ip_address']); - } - } - - if ($planName) { - $info->addChild('plan-name', $planName); - } - - $response = $this->_client->request($packet); - return new Struct\Info($response); - } - - /** - * @param string $field - * @param integer|string $value - * @return bool - */ - public function delete($field, $value) - { - return $this->_delete($field, $value); - } - - /** - * @param string $field - * @param integer|string $value - * @return Struct\GeneralInfo - */ - public function get($field, $value) - { - $items = $this->_getItems(Struct\GeneralInfo::class, 'gen_info', $field, $value); - return reset($items); - } - - /** - * @return Struct\GeneralInfo[] - */ - public function getAll() - { - return $this->_getItems(Struct\GeneralInfo::class, 'gen_info'); - } - -} diff --git a/src/PleskX/Api/Struct.php b/src/PleskX/Api/Struct.php deleted file mode 100644 index c76c1d38..00000000 --- a/src/PleskX/Api/Struct.php +++ /dev/null @@ -1,62 +0,0 @@ -{key($property)}; - } else { - $classPropertyName = $this->_underToCamel(str_replace('-', '_', $property)); - $value = $apiResponse->$property; - } - - $reflectionProperty = new \ReflectionProperty($this, $classPropertyName); - $docBlock = $reflectionProperty->getDocComment(); - $propertyType = preg_replace('/^.+ @var ([a-z]+) .+$/', '\1', $docBlock); - - if ('string' == $propertyType) { - $value = (string)$value; - } else if ('integer' == $propertyType) { - $value = (int)$value; - } else if ('boolean' == $propertyType) { - $value = in_array((string)$value, ['true', 'on', 'enabled']); - } else { - throw new \Exception("Unknown property type '$propertyType'."); - } - - $this->$classPropertyName = $value; - } - } - - /** - * Convert underscore separated words into camel case - * - * @param string $under - * @return string - */ - private function _underToCamel($under) - { - $under = '_' . str_replace('_', ' ', strtolower($under)); - return ltrim(str_replace(' ', '', ucwords($under)), '_'); - } - -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Certificate/Info.php b/src/PleskX/Api/Struct/Certificate/Info.php deleted file mode 100644 index 77f012de..00000000 --- a/src/PleskX/Api/Struct/Certificate/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - ['csr' => 'request'], - ['pvt' => 'privateKey'], - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Customer/GeneralInfo.php b/src/PleskX/Api/Struct/Customer/GeneralInfo.php deleted file mode 100644 index b1196949..00000000 --- a/src/PleskX/Api/Struct/Customer/GeneralInfo.php +++ /dev/null @@ -1,69 +0,0 @@ -_initScalarProperties($apiResponse, [ - ['cname' => 'company'], - ['pname' => 'personalName'], - 'login', - 'guid', - 'email', - 'phone', - 'fax', - 'address', - ['pcode' => 'postalCode'], - 'city', - 'state', - 'country', - 'external-id', - 'description', - ]); - } -} diff --git a/src/PleskX/Api/Struct/Customer/Info.php b/src/PleskX/Api/Struct/Customer/Info.php deleted file mode 100644 index 75199d77..00000000 --- a/src/PleskX/Api/Struct/Customer/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'guid', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Database/Info.php b/src/PleskX/Api/Struct/Database/Info.php deleted file mode 100644 index a85c6033..00000000 --- a/src/PleskX/Api/Struct/Database/Info.php +++ /dev/null @@ -1,37 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'name', - 'type', - 'webspace-id', - 'db-server-id', - 'default-user-id', - ]); - } -} diff --git a/src/PleskX/Api/Struct/Database/UserInfo.php b/src/PleskX/Api/Struct/Database/UserInfo.php deleted file mode 100644 index af367bac..00000000 --- a/src/PleskX/Api/Struct/Database/UserInfo.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'login', - 'db-id', - ]); - } -} diff --git a/src/PleskX/Api/Struct/DatabaseServer/Info.php b/src/PleskX/Api/Struct/DatabaseServer/Info.php deleted file mode 100644 index 9daa4fff..00000000 --- a/src/PleskX/Api/Struct/DatabaseServer/Info.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'host', - 'port', - 'type', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Dns/Info.php b/src/PleskX/Api/Struct/Dns/Info.php deleted file mode 100644 index e5021668..00000000 --- a/src/PleskX/Api/Struct/Dns/Info.php +++ /dev/null @@ -1,41 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'site-id', - 'site-alias-id', - 'type', - 'host', - 'value', - 'opt', - ]); - } -} diff --git a/src/PleskX/Api/Struct/EventLog/DetailedEvent.php b/src/PleskX/Api/Struct/EventLog/DetailedEvent.php deleted file mode 100644 index 0c399ecd..00000000 --- a/src/PleskX/Api/Struct/EventLog/DetailedEvent.php +++ /dev/null @@ -1,41 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'type', - 'time', - 'class', - ['obj_id' => 'objectId'], - 'user', - 'host', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/EventLog/Event.php b/src/PleskX/Api/Struct/EventLog/Event.php deleted file mode 100644 index 3797371f..00000000 --- a/src/PleskX/Api/Struct/EventLog/Event.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'type', - 'time', - 'class', - 'id', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Ip/Info.php b/src/PleskX/Api/Struct/Ip/Info.php deleted file mode 100644 index 29ec7ed7..00000000 --- a/src/PleskX/Api/Struct/Ip/Info.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'ip_address', - 'netmask', - 'type', - 'interface', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Locale/Info.php b/src/PleskX/Api/Struct/Locale/Info.php deleted file mode 100644 index 4f340166..00000000 --- a/src/PleskX/Api/Struct/Locale/Info.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - ['lang' => 'language'], - 'country' - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Mail/Info.php b/src/PleskX/Api/Struct/Mail/Info.php deleted file mode 100644 index be00923b..00000000 --- a/src/PleskX/Api/Struct/Mail/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'name', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Reseller/GeneralInfo.php b/src/PleskX/Api/Struct/Reseller/GeneralInfo.php deleted file mode 100644 index 8a9232bf..00000000 --- a/src/PleskX/Api/Struct/Reseller/GeneralInfo.php +++ /dev/null @@ -1,32 +0,0 @@ -_initScalarProperties($apiResponse->{'gen-info'}, [ - ['pname' => 'personalName'], - 'login', - ]); - - $this->permissions = []; - foreach ($apiResponse->permissions->permission as $permissionInfo) { - $this->permissions[(string)$permissionInfo->name] = (string)$permissionInfo->value; - } - } -} diff --git a/src/PleskX/Api/Struct/Reseller/Info.php b/src/PleskX/Api/Struct/Reseller/Info.php deleted file mode 100644 index 4482abb7..00000000 --- a/src/PleskX/Api/Struct/Reseller/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'guid', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/SecretKey/Info.php b/src/PleskX/Api/Struct/SecretKey/Info.php deleted file mode 100644 index d0729c76..00000000 --- a/src/PleskX/Api/Struct/SecretKey/Info.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'key', - 'ip_address', - 'description', - 'login', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/Admin.php b/src/PleskX/Api/Struct/Server/Admin.php deleted file mode 100644 index 554f44ae..00000000 --- a/src/PleskX/Api/Struct/Server/Admin.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - ['admin_cname' => 'companyName'], - ['admin_pname' => 'name'], - ['admin_email' => 'email'], - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/GeneralInfo.php b/src/PleskX/Api/Struct/Server/GeneralInfo.php deleted file mode 100644 index 332332de..00000000 --- a/src/PleskX/Api/Struct/Server/GeneralInfo.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'server_name', - 'server_guid', - 'mode', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/Preferences.php b/src/PleskX/Api/Struct/Server/Preferences.php deleted file mode 100644 index e19fd933..00000000 --- a/src/PleskX/Api/Struct/Server/Preferences.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'stat_ttl', - 'traffic_accounting', - 'restart_apache_interval', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/SessionPreferences.php b/src/PleskX/Api/Struct/Server/SessionPreferences.php deleted file mode 100644 index a222a92d..00000000 --- a/src/PleskX/Api/Struct/Server/SessionPreferences.php +++ /dev/null @@ -1,17 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'login_timeout', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/Statistics.php b/src/PleskX/Api/Struct/Server/Statistics.php deleted file mode 100644 index 5fb75fd2..00000000 --- a/src/PleskX/Api/Struct/Server/Statistics.php +++ /dev/null @@ -1,20 +0,0 @@ -objects = new Statistics\Objects($apiResponse->objects); - $this->version = new Statistics\Version($apiResponse->version); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/Statistics/Objects.php b/src/PleskX/Api/Struct/Server/Statistics/Objects.php deleted file mode 100644 index 6d518867..00000000 --- a/src/PleskX/Api/Struct/Server/Statistics/Objects.php +++ /dev/null @@ -1,22 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'clients', - 'domains', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/Statistics/Version.php b/src/PleskX/Api/Struct/Server/Statistics/Version.php deleted file mode 100644 index 6ac5d1e1..00000000 --- a/src/PleskX/Api/Struct/Server/Statistics/Version.php +++ /dev/null @@ -1,22 +0,0 @@ -_initScalarProperties($apiResponse, [ - ['plesk_name' => 'internalName'], - ['plesk_version' => 'version'], - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Server/UpdatesInfo.php b/src/PleskX/Api/Struct/Server/UpdatesInfo.php deleted file mode 100644 index a29da158..00000000 --- a/src/PleskX/Api/Struct/Server/UpdatesInfo.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'last_installed_update', - 'install_updates_automatically', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/ServicePlan/Info.php b/src/PleskX/Api/Struct/ServicePlan/Info.php deleted file mode 100644 index e873cb86..00000000 --- a/src/PleskX/Api/Struct/ServicePlan/Info.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'name', - 'guid', - 'external-id', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Session/Info.php b/src/PleskX/Api/Struct/Session/Info.php deleted file mode 100644 index 2cae900f..00000000 --- a/src/PleskX/Api/Struct/Session/Info.php +++ /dev/null @@ -1,37 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'type', - 'ip-address', - 'login', - 'login-time', - 'idle', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Site/GeneralInfo.php b/src/PleskX/Api/Struct/Site/GeneralInfo.php deleted file mode 100644 index c02c4464..00000000 --- a/src/PleskX/Api/Struct/Site/GeneralInfo.php +++ /dev/null @@ -1,29 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'name', - 'ascii-name', - 'guid', - 'description', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Site/HostingInfo.php b/src/PleskX/Api/Struct/Site/HostingInfo.php deleted file mode 100755 index db1af385..00000000 --- a/src/PleskX/Api/Struct/Site/HostingInfo.php +++ /dev/null @@ -1,23 +0,0 @@ -vrt_hst->property as $property) { - $this->properties[(string)$property->name] = (string)$property->value; - } - $this->_initScalarProperties($apiResponse->vrt_hst, [ - 'ip_address', - ]); - } -} diff --git a/src/PleskX/Api/Struct/Site/Info.php b/src/PleskX/Api/Struct/Site/Info.php deleted file mode 100644 index 46bcccb6..00000000 --- a/src/PleskX/Api/Struct/Site/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'guid', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/SiteAlias/Info.php b/src/PleskX/Api/Struct/SiteAlias/Info.php deleted file mode 100644 index 911d66b9..00000000 --- a/src/PleskX/Api/Struct/SiteAlias/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'status', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Subdomain/Info.php b/src/PleskX/Api/Struct/Subdomain/Info.php deleted file mode 100644 index 6a81d021..00000000 --- a/src/PleskX/Api/Struct/Subdomain/Info.php +++ /dev/null @@ -1,32 +0,0 @@ -properties = []; - $this->_initScalarProperties($apiResponse, [ - 'id', - 'parent', - 'name' - ]); - foreach ($apiResponse->property as $propertyInfo) { - $this->properties[(string)$propertyInfo->name] = (string)$propertyInfo->value; - } - } -} diff --git a/src/PleskX/Api/Struct/Ui/CustomButton.php b/src/PleskX/Api/Struct/Ui/CustomButton.php deleted file mode 100644 index e795583c..00000000 --- a/src/PleskX/Api/Struct/Ui/CustomButton.php +++ /dev/null @@ -1,45 +0,0 @@ -_initScalarProperties($apiResponse, ['id']); - $this->_initScalarProperties($apiResponse->properties, [ - 'sort_key', - 'public', - 'internal', - ['noframe' => 'noFrame'], - 'place', - 'url', - 'text', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/GeneralInfo.php b/src/PleskX/Api/Struct/Webspace/GeneralInfo.php deleted file mode 100644 index 60ba9be5..00000000 --- a/src/PleskX/Api/Struct/Webspace/GeneralInfo.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'name', - 'guid', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/HostingPropertyInfo.php b/src/PleskX/Api/Struct/Webspace/HostingPropertyInfo.php deleted file mode 100644 index a933df87..00000000 --- a/src/PleskX/Api/Struct/Webspace/HostingPropertyInfo.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'name', - 'type', - 'label', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/Info.php b/src/PleskX/Api/Struct/Webspace/Info.php deleted file mode 100644 index 6a1717d4..00000000 --- a/src/PleskX/Api/Struct/Webspace/Info.php +++ /dev/null @@ -1,21 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'id', - 'guid', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/LimitDescriptor.php b/src/PleskX/Api/Struct/Webspace/LimitDescriptor.php deleted file mode 100644 index 2f182117..00000000 --- a/src/PleskX/Api/Struct/Webspace/LimitDescriptor.php +++ /dev/null @@ -1,19 +0,0 @@ -limits = []; - - foreach ($apiResponse->descriptor->property as $propertyInfo) { - $this->limits[(string)$propertyInfo->name] = new LimitInfo($propertyInfo); - } - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/LimitInfo.php b/src/PleskX/Api/Struct/Webspace/LimitInfo.php deleted file mode 100644 index b7d73791..00000000 --- a/src/PleskX/Api/Struct/Webspace/LimitInfo.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'name', - 'type', - 'label', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/PermissionDescriptor.php b/src/PleskX/Api/Struct/Webspace/PermissionDescriptor.php deleted file mode 100644 index 48d3b6e7..00000000 --- a/src/PleskX/Api/Struct/Webspace/PermissionDescriptor.php +++ /dev/null @@ -1,19 +0,0 @@ -permissions = []; - - foreach ($apiResponse->descriptor->property as $propertyInfo) { - $this->permissions[(string)$propertyInfo->name] = new PermissionInfo($propertyInfo); - } - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/PermissionInfo.php b/src/PleskX/Api/Struct/Webspace/PermissionInfo.php deleted file mode 100644 index c40a496f..00000000 --- a/src/PleskX/Api/Struct/Webspace/PermissionInfo.php +++ /dev/null @@ -1,25 +0,0 @@ -_initScalarProperties($apiResponse, [ - 'name', - 'type', - 'label', - ]); - } -} \ No newline at end of file diff --git a/src/PleskX/Api/Struct/Webspace/PhysicalHostingDescriptor.php b/src/PleskX/Api/Struct/Webspace/PhysicalHostingDescriptor.php deleted file mode 100644 index aae73c5c..00000000 --- a/src/PleskX/Api/Struct/Webspace/PhysicalHostingDescriptor.php +++ /dev/null @@ -1,19 +0,0 @@ -properties = []; - - foreach ($apiResponse->descriptor->property as $propertyInfo) { - $this->properties[(string)$propertyInfo->name] = new HostingPropertyInfo($propertyInfo); - } - } -} \ No newline at end of file diff --git a/src/PleskX/Api/XmlResponse.php b/src/PleskX/Api/XmlResponse.php deleted file mode 100644 index 8c3ce61c..00000000 --- a/src/PleskX/Api/XmlResponse.php +++ /dev/null @@ -1,23 +0,0 @@ -xpath('//' . $node)[0]; - } - -} \ No newline at end of file diff --git a/tests/AbstractTestCase.php b/tests/AbstractTestCase.php new file mode 100644 index 00000000..e976f3a1 --- /dev/null +++ b/tests/AbstractTestCase.php @@ -0,0 +1,113 @@ +setCredentials($login, $password); + + $proxy = getenv('REMOTE_PROXY'); + if ($proxy) { + static::$client->setProxy($proxy); + } + } + + public static function tearDownAfterClass(): void + { + foreach (self::$webspaces as $webspace) { + try { + static::$client->webspace()->delete('id', $webspace->id); + // phpcs:ignore + } catch (\Exception $e) { + } + } + + foreach (self::$servicePlans as $servicePlan) { + try { + static::$client->servicePlan()->delete('id', $servicePlan->id); + // phpcs:ignore + } catch (\Exception $e) { + } + } + + foreach (self::$servicePlanAddons as $servicePlanAddon) { + try { + static::$client->servicePlanAddon()->delete('id', $servicePlanAddon->id); + // phpcs:ignore + } catch (\Exception $e) { + } + } + } + + protected static function getIpAddress(): string + { + $ips = static::$client->ip()->get(); + $ipInfo = reset($ips); + + return $ipInfo->ipAddress; + } + + protected static function createWebspace(): \PleskX\Api\Struct\Webspace\Info + { + $id = uniqid(); + $webspace = static::$client->webspace()->create( + [ + 'name' => "test{$id}.test", + 'ip_address' => static::getIpAddress(), + ], + [ + 'ftp_login' => "u{$id}", + 'ftp_password' => PasswordProvider::STRONG_PASSWORD, + ] + ); + self::$webspaces[] = $webspace; + + return $webspace; + } + + protected static function createServicePlan(): \PleskX\Api\Struct\ServicePlan\Info + { + $id = uniqid(); + $servicePlan = static::$client->servicePlan()->create(['name' => "test{$id}plan"]); + + self::$servicePlans[] = $servicePlan; + + return $servicePlan; + } + + protected static function createServicePlanAddon(): \PleskX\Api\Struct\ServicePlanAddon\Info + { + $id = uniqid(); + $servicePlanAddon = static::$client->servicePlanAddon()->create(['name' => "test{$id}planaddon"]); + + self::$servicePlanAddons[] = $servicePlanAddon; + + return $servicePlanAddon; + } +} diff --git a/tests/ApiClientTest.php b/tests/ApiClientTest.php index ca8e1a33..3fd90546 100644 --- a/tests/ApiClientTest.php +++ b/tests/ApiClientTest.php @@ -1,103 +1,102 @@ getPacket('100.0.0'); + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1005); + + $packet = static::$client->getPacket('100.0.0'); $packet->addChild('server')->addChild('get_protos'); - static::$_client->request($packet); + static::$client->request($packet); } - /** - * @expectedException \PleskX\Api\Exception - * @expectedExceptionCode 1014 - */ public function testUnknownOperator() { - $packet = static::$_client->getPacket(); + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1014); + + $packet = static::$client->getPacket(); $packet->addChild('unknown'); - static::$_client->request($packet); + static::$client->request($packet); } - /** - * @expectedException \PleskX\Api\Exception - * @expectedExceptionCode 1014 - */ public function testInvalidXmlRequest() { - static::$_client->request(''); + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1014); + + static::$client->request(''); } - /** - * @expectedException \PleskX\Api\Exception - * @expectedExceptionCode 1001 - */ public function testInvalidCredentials() { - $host = static::$_client->getHost(); - $port = static::$_client->getPort(); - $protocol = static::$_client->getProtocol(); - $client = new PleskX\Api\Client($host, $port, $protocol); + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1001); + + $host = static::$client->getHost(); + $port = static::$client->getPort(); + $protocol = static::$client->getProtocol(); + $client = new \PleskX\Api\Client($host, $port, $protocol); $client->setCredentials('bad-login', 'bad-password'); - $packet = static::$_client->getPacket(); + $packet = static::$client->getPacket(); $packet->addChild('server')->addChild('get_protos'); $client->request($packet); } - /** - * @expectedException \PleskX\Api\Exception - * @expectedExceptionCode 11003 - */ public function testInvalidSecretKey() { - $host = static::$_client->getHost(); - $port = static::$_client->getPort(); - $protocol = static::$_client->getProtocol(); - $client = new PleskX\Api\Client($host, $port, $protocol); + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(11003); + + $host = static::$client->getHost(); + $port = static::$client->getPort(); + $protocol = static::$client->getProtocol(); + $client = new \PleskX\Api\Client($host, $port, $protocol); $client->setSecretKey('bad-key'); - $packet = static::$_client->getPacket(); + $packet = static::$client->getPacket(); $packet->addChild('server')->addChild('get_protos'); $client->request($packet); } public function testLatestMajorProtocol() { - $packet = static::$_client->getPacket('1.6'); + $packet = static::$client->getPacket('1.6'); $packet->addChild('server')->addChild('get_protos'); - static::$_client->request($packet); + $result = static::$client->request($packet); + $this->assertEquals('ok', $result->status); } public function testLatestMinorProtocol() { - $packet = static::$_client->getPacket('1.6.5'); + $packet = static::$client->getPacket('1.6.5'); $packet->addChild('server')->addChild('get_protos'); - static::$_client->request($packet); + $result = static::$client->request($packet); + $this->assertEquals('ok', $result->status); } public function testRequestShortSyntax() { - $response = static::$_client->request('server.get.gen_info'); + $response = static::$client->request('server.get.gen_info'); $this->assertGreaterThan(0, strlen($response->gen_info->server_name)); } public function testOperatorPlainRequest() { - $response = static::$_client->server()->request('get.gen_info'); + $response = static::$client->server()->request('get.gen_info'); $this->assertGreaterThan(0, strlen($response->gen_info->server_name)); $this->assertEquals(36, strlen($response->getValue('server_guid'))); } public function testRequestArraySyntax() { - $response = static::$_client->request([ + $response = static::$client->request([ 'server' => [ 'get' => [ 'gen_info' => '', @@ -109,31 +108,30 @@ public function testRequestArraySyntax() public function testOperatorArraySyntax() { - $response = static::$_client->server()->request(['get' => ['gen_info' => '']]); + $response = static::$client->server()->request(['get' => ['gen_info' => '']]); $this->assertGreaterThan(0, strlen($response->gen_info->server_name)); } public function testMultiRequest() { - $responses = static::$_client->multiRequest([ + $responses = static::$client->multiRequest([ 'server.get_protos', 'server.get.gen_info', ]); $this->assertCount(2, $responses); - $protos = (array)$responses[0]->protos->proto; + $protos = (array) $responses[0]->protos->proto; $generalInfo = $responses[1]; $this->assertContains('1.6.6.0', $protos); $this->assertGreaterThan(0, strlen($generalInfo->gen_info->server_name)); } - /** - * @expectedException \PleskX\Api\Client\Exception - */ public function testConnectionError() { + $this->expectException(\PleskX\Api\Client\Exception::class); + $client = new \PleskX\Api\Client('invalid-host.dom'); $client->server()->getProtos(); } @@ -158,17 +156,18 @@ public function testGetProtocol() public function testSetVerifyResponse() { - static::$_client->setVerifyResponse(function ($xml) { + static::$client->setVerifyResponse(function ($xml) { if ($xml->xpath('//proto')) { throw new Exception('proto'); } }); + try { - static::$_client->server()->getProtos(); + static::$client->server()->getProtos(); } catch (Exception $e) { $this->assertEquals('proto', $e->getMessage()); } finally { - static::$_client->setVerifyResponse(); + static::$client->setVerifyResponse(); } } } diff --git a/tests/CertificateTest.php b/tests/CertificateTest.php index 5ead19e9..bb885986 100644 --- a/tests/CertificateTest.php +++ b/tests/CertificateTest.php @@ -1,24 +1,97 @@ 2048, + 'country' => 'CH', + 'state' => 'Schaffhausen', + 'location' => 'Schaffhausen', + 'company' => 'Plesk', + 'email' => 'info@plesk.com', + 'name' => 'plesk.com', + ]; + private array $distinguishedNames = [ + "countryName" => "CH", + "stateOrProvinceName" => "Schaffhausen", + "localityName" => "Schaffhausen", + "organizationName" => "Plesk", + "emailAddress" => "info@plesk.com" + ]; public function testGenerate() { - $certificate = static::$_client->certificate()->generate([ - 'bits' => 2048, - 'country' => 'RU', - 'state' => 'NSO', - 'location' => 'Novosibirsk', - 'company' => 'Plesk', - 'email' => 'info@plesk.com', - 'name' => 'plesk.com' - ]); + $certificate = static::$client->certificate()->generate($this->certificateProperties); $this->assertGreaterThan(0, strlen($certificate->request)); $this->assertStringStartsWith('-----BEGIN CERTIFICATE REQUEST-----', $certificate->request); $this->assertGreaterThan(0, strlen($certificate->privateKey)); $this->assertStringStartsWith('-----BEGIN PRIVATE KEY-----', $certificate->privateKey); } + public function testInstall() + { + $certificate = static::$client->certificate()->generate($this->certificateProperties); + + $result = static::$client->certificate()->install([ + 'name' => 'test', + 'admin' => true, + ], $certificate->request, $certificate->privateKey); + $this->assertTrue($result); + + static::$client->certificate()->delete('test', ['admin' => true]); + } + + public function testUpdate() + { + $payLoad = [ + 'name' => 'test', + 'admin' => true, + ]; + $certificate = static::$client->certificate()->generate($this->certificateProperties); + static::$client->certificate()->install($payLoad, $certificate); + + $certificate = $this->generateCertificateOpenSsl($this->distinguishedNames); + $result = static::$client->certificate()->update($payLoad, $certificate); + $this->assertTrue($result); + + static::$client->certificate()->delete('test', ['admin' => true]); + } + + public function testDelete() + { + $certificate = static::$client->certificate()->generate($this->certificateProperties); + + static::$client->certificate()->install([ + 'name' => 'test', + 'admin' => true, + ], $certificate); + + $result = static::$client->certificate()->delete('test', ['admin' => true]); + $this->assertTrue($result); + } + + private function generateCertificateOpenSsl(array $dn): Struct\Info + { + $privkey = openssl_pkey_new([ + "private_key_bits" => 2048, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + ]); + $csr = openssl_csr_new($dn, $privkey, ['digest_alg' => 'sha256']); + $x509 = openssl_csr_sign($csr, null, $privkey, $days = 365, ['digest_alg' => 'sha256']); + + openssl_csr_export($csr, $csrout); + openssl_x509_export($x509, $certout); + openssl_pkey_export($privkey, $pkeyout); + + return new Struct\Info([ + 'publicKey' => $certout, + 'request' => $csrout, + 'privateKey' => $pkeyout + ]); + } } diff --git a/tests/CustomerTest.php b/tests/CustomerTest.php index a6ac291b..02e4709c 100644 --- a/tests/CustomerTest.php +++ b/tests/CustomerTest.php @@ -1,69 +1,128 @@ 'Plesk', - 'pname' => 'John Smith', - 'login' => 'john-unit-test', - 'passwd' => 'simple-password', - 'email' => 'john@smith.com', - 'external-id' => 'link:12345', - 'description' => 'Good guy', - ]; + public function setUp(): void + { + $this->customerProperties = [ + 'cname' => 'Plesk', + 'pname' => 'John Smith', + 'login' => 'john-unit-test', + 'passwd' => PasswordProvider::STRONG_PASSWORD, + 'email' => 'john@smith.com', + 'external-id' => 'link:12345', + 'description' => 'Good guy', + ]; + } public function testCreate() { - $customer = static::$_client->customer()->create($this->_customerProperties); - $this->assertInternalType('integer', $customer->id); + $customer = static::$client->customer()->create($this->customerProperties); + $this->assertIsInt($customer->id); $this->assertGreaterThan(0, $customer->id); - static::$_client->customer()->delete('id', $customer->id); + static::$client->customer()->delete('id', $customer->id); } public function testDelete() { - $customer = static::$_client->customer()->create($this->_customerProperties); - $result = static::$_client->customer()->delete('id', $customer->id); + $customer = static::$client->customer()->create($this->customerProperties); + $result = static::$client->customer()->delete('id', $customer->id); $this->assertTrue($result); } public function testGet() { - $customer = static::$_client->customer()->create($this->_customerProperties); - $customerInfo = static::$_client->customer()->get('id', $customer->id); + $customer = static::$client->customer()->create($this->customerProperties); + $customerInfo = static::$client->customer()->get('id', $customer->id); $this->assertEquals('Plesk', $customerInfo->company); $this->assertEquals('John Smith', $customerInfo->personalName); $this->assertEquals('john-unit-test', $customerInfo->login); $this->assertEquals('john@smith.com', $customerInfo->email); $this->assertEquals('Good guy', $customerInfo->description); $this->assertEquals('link:12345', $customerInfo->externalId); + $this->assertEquals($customer->id, $customerInfo->id); - static::$_client->customer()->delete('id', $customer->id); + static::$client->customer()->delete('id', $customer->id); } public function testGetAll() { - static::$_client->customer()->create([ + $keyInfo = static::$client->server()->getKeyInfo(); + + if (!KeyLimitChecker::checkByType($keyInfo, KeyLimitChecker::LIMIT_CLIENTS, 2)) { + $this->markTestSkipped('License does not allow to create more than 1 customer.'); + } + + static::$client->customer()->create([ 'pname' => 'John Smith', 'login' => 'customer-a', - 'passwd' => 'simple-password', + 'passwd' => PasswordProvider::STRONG_PASSWORD, ]); - static::$_client->customer()->create([ + static::$client->customer()->create([ 'pname' => 'Mike Black', 'login' => 'customer-b', - 'passwd' => 'simple-password', + 'passwd' => PasswordProvider::STRONG_PASSWORD, ]); - $customersInfo = static::$_client->customer()->getAll(); - $this->assertCount(2, $customersInfo); - $this->assertEquals('John Smith', $customersInfo[0]->personalName); - $this->assertEquals('customer-a', $customersInfo[0]->login); + $customersInfo = static::$client->customer()->getAll(); + $this->assertIsArray($customersInfo); + + $customersCheck = array_filter($customersInfo, function ($value) { + return $value->personalName === 'John Smith' || $value->personalName === 'Mike Black'; + }); + $this->assertCount(2, $customersCheck); + + static::$client->customer()->delete('login', 'customer-a'); + static::$client->customer()->delete('login', 'customer-b'); + } + + public function testGetAllEmpty() + { + $customersInfo = static::$client->customer()->getAll(); + $this->assertCount(0, $customersInfo); + } + + public function testEnable() + { + $customer = static::$client->customer()->create($this->customerProperties); + static::$client->customer()->disable('id', $customer->id); + static::$client->customer()->enable('id', $customer->id); + $customerInfo = static::$client->customer()->get('id', $customer->id); + $this->assertTrue($customerInfo->enabled); + + static::$client->customer()->delete('id', $customer->id); + } + + public function testDisable() + { + $customer = static::$client->customer()->create($this->customerProperties); + static::$client->customer()->disable('id', $customer->id); + $customerInfo = static::$client->customer()->get('id', $customer->id); + $this->assertFalse($customerInfo->enabled); - static::$_client->customer()->delete('login', 'customer-a'); - static::$_client->customer()->delete('login', 'customer-b'); + static::$client->customer()->delete('id', $customer->id); } + public function testSetProperties() + { + $customer = static::$client->customer()->create($this->customerProperties); + static::$client->customer()->setProperties('id', $customer->id, [ + 'pname' => 'Mike Black', + 'email' => 'mike@black.com', + ]); + $customerInfo = static::$client->customer()->get('id', $customer->id); + $this->assertEquals('Mike Black', $customerInfo->personalName); + $this->assertEquals('mike@black.com', $customerInfo->email); + + static::$client->customer()->delete('id', $customer->id); + } } diff --git a/tests/DatabaseServerTest.php b/tests/DatabaseServerTest.php index 5ab1e372..d4934590 100644 --- a/tests/DatabaseServerTest.php +++ b/tests/DatabaseServerTest.php @@ -1,29 +1,36 @@ databaseServer()->getSupportedTypes(); + $types = static::$client->databaseServer()->getSupportedTypes(); $this->assertGreaterThan(0, count($types)); $this->assertContains('mysql', $types); } public function testGet() { - $dbServer = static::$_client->databaseServer()->get('id', 1); + $dbServer = static::$client->databaseServer()->get('id', 1); $this->assertEquals('localhost', $dbServer->host); $this->assertGreaterThan(0, $dbServer->port); } public function testGetAll() { - $dbServers = static::$_client->databaseServer()->getAll(); - $this->assertInternalType('array', $dbServers); + $dbServers = static::$client->databaseServer()->getAll(); + $this->assertIsArray($dbServers); $this->assertGreaterThan(0, count($dbServers)); $this->assertEquals('localhost', $dbServers[0]->host); } + public function testGetDefault() + { + $dbServer = static::$client->databaseServer()->getDefault('mysql'); + $this->assertEquals('mysql', $dbServer->type); + $this->assertGreaterThan(0, $dbServer->id); + } } diff --git a/tests/DatabaseTest.php b/tests/DatabaseTest.php index 2ab1e117..1b2b1c5f 100644 --- a/tests/DatabaseTest.php +++ b/tests/DatabaseTest.php @@ -1,237 +1,228 @@ webspace()->delete('id', static::$_webspace->id); + static::$webspace = static::createWebspace(); + static::$databaseServer = static::$client->databaseServer()->getDefault('mysql'); } public function testCreate() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->delete('id', $database->id); } public function testCreateUser() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $user = $this->_createUser([ + $user = $this->createUser([ 'db-id' => $database->id, 'login' => 'test_user1', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - static::$_client->database()->deleteUser('id', $user->id); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->deleteUser('id', $user->id); + static::$client->database()->delete('id', $database->id); } public function testUpdateUser() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $user = $this->_createUser([ + $user = $this->createUser([ 'db-id' => $database->id, 'login' => 'test_user1', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $updatedUser = static::$_client->database()->updateUser([ + $updatedUser = static::$client->database()->updateUser([ 'id' => $user->id, 'login' => 'test_user2', - 'password' => 'setup2Q' + 'password' => PasswordProvider::STRONG_PASSWORD, ]); $this->assertEquals(true, $updatedUser); - static::$_client->database()->deleteUser('id', $user->id); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->deleteUser('id', $user->id); + static::$client->database()->delete('id', $database->id); } public function testGetById() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $db = static::$_client->database()->get('id', $database->id); + $db = static::$client->database()->get('id', $database->id); $this->assertEquals('test1', $db->name); - $this->assertEquals('mysql', $db->type); - $this->assertEquals(static::$_webspace->id, $db->webspaceId); - $this->assertEquals(1, $db->dbServerId); + $this->assertEquals(static::$databaseServer->type, $db->type); + $this->assertEquals(static::$webspace->id, $db->webspaceId); + $this->assertEquals(static::$databaseServer->id, $db->dbServerId); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->delete('id', $database->id); } public function testGetAllByWebspaceId() { - $db1 = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $db1 = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $db2 = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $db2 = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test2', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $databases = static::$_client->database()->getAll('webspace-id', static::$_webspace->id); + $databases = static::$client->database()->getAll('webspace-id', static::$webspace->id); $this->assertEquals('test1', $databases[0]->name); $this->assertEquals('test2', $databases[1]->name); - $this->assertEquals(static::$_webspace->id, $databases[0]->webspaceId); - $this->assertEquals(1, $databases[1]->dbServerId); + $this->assertEquals(static::$webspace->id, $databases[0]->webspaceId); + $this->assertEquals(static::$databaseServer->id, $databases[1]->dbServerId); - static::$_client->database()->delete('id', $db1->id); - static::$_client->database()->delete('id', $db2->id); + static::$client->database()->delete('id', $db1->id); + static::$client->database()->delete('id', $db2->id); } public function testGetUserById() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $user = $this->_createUser([ + $user = $this->createUser([ 'db-id' => $database->id, 'login' => 'test_user1', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $dbUser = static::$_client->database()->getUser('id', $user->id); + $dbUser = static::$client->database()->getUser('id', $user->id); $this->assertEquals('test_user1', $dbUser->login); $this->assertEquals($database->id, $dbUser->dbId); - static::$_client->database()->deleteUser('id', $user->id); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->deleteUser('id', $user->id); + static::$client->database()->delete('id', $database->id); } public function testGetAllUsersByDbId() { - $db1 = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $db1 = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $db2 = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $db2 = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test2', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $user1 = $this->_createUser([ + $user1 = $this->createUser([ 'db-id' => $db1->id, 'login' => 'test_user1', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $user2 = $this->_createUser([ + $user2 = $this->createUser([ 'db-id' => $db1->id, 'login' => 'test_user2', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $user3 = $this->_createUser([ + $user3 = $this->createUser([ 'db-id' => $db2->id, 'login' => 'test_user3', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $dbUsers = static::$_client->database()->getAllUsers('db-id', $db1->id); + $dbUsers = static::$client->database()->getAllUsers('db-id', $db1->id); $this->assertEquals(2, count($dbUsers)); $this->assertEquals('test_user1', $dbUsers[0]->login); $this->assertEquals('test_user2', $dbUsers[1]->login); - static::$_client->database()->deleteUser('id', $user1->id); - static::$_client->database()->deleteUser('id', $user2->id); - static::$_client->database()->deleteUser('id', $user3->id); - static::$_client->database()->delete('id', $db1->id); - static::$_client->database()->delete('id', $db2->id); + static::$client->database()->deleteUser('id', $user1->id); + static::$client->database()->deleteUser('id', $user2->id); + static::$client->database()->deleteUser('id', $user3->id); + static::$client->database()->delete('id', $db1->id); + static::$client->database()->delete('id', $db2->id); } public function testDelete() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $result = static::$_client->database()->delete('id', $database->id); + $result = static::$client->database()->delete('id', $database->id); $this->assertTrue($result); } public function testDeleteUser() { - $database = $this->_createDatabase([ - 'webspace-id' => static::$_webspace->id, + $database = $this->createDatabase([ + 'webspace-id' => static::$webspace->id, 'name' => 'test1', - 'type' => 'mysql', - 'db-server-id' => 1 + 'type' => static::$databaseServer->type, + 'db-server-id' => static::$databaseServer->id, ]); - $user = $this->_createUser([ + $user = $this->createUser([ 'db-id' => $database->id, 'login' => 'test_user1', - 'password' => 'setup1Q', + 'password' => PasswordProvider::STRONG_PASSWORD, ]); - $result = static::$_client->database()->deleteUser('id', $user->id); + $result = static::$client->database()->deleteUser('id', $user->id); $this->assertTrue($result); - static::$_client->database()->delete('id', $database->id); + static::$client->database()->delete('id', $database->id); } - /** - * @param array $params - * @return \PleskX\Api\Struct\Database\Info - */ - private function _createDatabase(array $params) + private function createDatabase(array $params): \PleskX\Api\Struct\Database\Info { - $database = static::$_client->database()->create($params); - $this->assertInternalType('integer', $database->id); + $database = static::$client->database()->create($params); + $this->assertIsInt($database->id); $this->assertGreaterThan(0, $database->id); + return $database; } - /** - * @param array $params - * @return \PleskX\Api\Struct\Database\UserInfo - */ - private function _createUser(array $params) + private function createUser(array $params): \PleskX\Api\Struct\Database\UserInfo { - $user = static::$_client->database()->createUser($params); - $this->assertInternalType('integer', $user->id); + $user = static::$client->database()->createUser($params); + $this->assertIsInt($user->id); $this->assertGreaterThan(0, $user->id); + return $user; } } diff --git a/tests/DnsTemplateTest.php b/tests/DnsTemplateTest.php new file mode 100644 index 00000000..14fc351b --- /dev/null +++ b/tests/DnsTemplateTest.php @@ -0,0 +1,91 @@ +server()->getServiceStates(); + static::$isDnsSupported = $serviceStates['dns'] && ('running' == $serviceStates['dns']['state']); + } + + protected function setUp(): void + { + parent::setUp(); + + if (!static::$isDnsSupported) { + $this->markTestSkipped('DNS system is not supported.'); + } + } + + public function testCreate() + { + $dns = static::$client->dnsTemplate()->create([ + 'type' => 'TXT', + 'host' => 'test.create', + 'value' => 'value', + ]); + $this->assertIsInt($dns->id); + $this->assertGreaterThan(0, $dns->id); + $this->assertEquals(0, $dns->siteId); + $this->assertEquals(0, $dns->siteAliasId); + static::$client->dnsTemplate()->delete('id', $dns->id); + } + + public function testGetById() + { + $dns = static::$client->dnsTemplate()->create([ + 'type' => 'TXT', + 'host' => 'test.get.by.id', + 'value' => 'value', + ]); + + $dnsInfo = static::$client->dnsTemplate()->get('id', $dns->id); + $this->assertEquals('TXT', $dnsInfo->type); + $this->assertEquals('value', $dnsInfo->value); + + static::$client->dnsTemplate()->delete('id', $dns->id); + } + + public function testGetAll() + { + $dns = static::$client->dnsTemplate()->create([ + 'type' => 'TXT', + 'host' => 'test.get.all', + 'value' => 'value', + ]); + $dns2 = static::$client->dnsTemplate()->create([ + 'type' => 'TXT', + 'host' => 'test.get.all', + 'value' => 'value2', + ]); + $dnsInfo = static::$client->dnsTemplate()->getAll(); + $dsRecords = []; + foreach ($dnsInfo as $dnsRec) { + if ('TXT' === $dnsRec->type && 0 === strpos($dnsRec->host, 'test.get.all')) { + $dsRecords[] = $dnsRec; + } + } + $this->assertCount(2, $dsRecords); + + static::$client->dnsTemplate()->delete('id', $dns->id); + static::$client->dnsTemplate()->delete('id', $dns2->id); + } + + public function testDelete() + { + $dns = static::$client->dnsTemplate()->create([ + 'type' => 'TXT', + 'host' => 'test.delete', + 'value' => 'value', + ]); + $result = static::$client->dnsTemplate()->delete('id', $dns->id); + $this->assertTrue($result); + } +} diff --git a/tests/DnsTest.php b/tests/DnsTest.php index d3cfd8da..e0282b1a 100644 --- a/tests/DnsTest.php +++ b/tests/DnsTest.php @@ -1,112 +1,161 @@ server()->getServiceStates(); - static::$_isDnsSupported = $serviceStates['dns'] && ('running' == $serviceStates['dns']['state']); - - static::$_webspace = static::_createWebspace('example.dom'); - } + $serviceStates = static::$client->server()->getServiceStates(); + static::$isDnsSupported = isset($serviceStates['dns']) && ('running' == $serviceStates['dns']['state']); - public static function tearDownAfterClass() - { - parent::tearDownAfterClass(); - static::$_client->webspace()->delete('id', static::$_webspace->id); + if (static::$isDnsSupported) { + static::$webspace = static::createWebspace(); + } } - protected function setUp() + protected function setUp(): void { parent::setUp(); - if (!static::$_isDnsSupported) { + if (!static::$isDnsSupported) { $this->markTestSkipped('DNS system is not supported.'); } } public function testCreate() { - $dns = static::$_client->dns()->create([ - 'site-id' => static::$_webspace->id, + $dns = static::$client->dns()->create([ + 'site-id' => static::$webspace->id, 'type' => 'TXT', 'host' => 'host', - 'value' => 'value' + 'value' => 'value', ]); - $this->assertInternalType('integer', $dns->id); + $this->assertIsInt($dns->id); $this->assertGreaterThan(0, $dns->id); - static::$_client->dns()->delete('id', $dns->id); + static::$client->dns()->delete('id', $dns->id); + } + + /** + * @return \SimpleXMLElement[] + */ + public function testBulkCreate(): array + { + $response = static::$client->dns()->bulkCreate([ + [ + 'site-id' => static::$webspace->id, + 'type' => 'TXT', + 'host' => 'host', + 'value' => 'value', + ], + [ + 'site-id' => static::$webspace->id, + 'type' => 'A', + 'host' => 'host', + 'value' => '1.1.1.1', + ], + [ + 'site-id' => static::$webspace->id, + 'type' => 'MX', + 'host' => 'custom-mail', + 'value' => '1.1.1.1', + 'opt' => '10', + ], + ]); + + $this->assertCount(3, $response); + + foreach ($response as $xml) { + $this->assertEquals('ok', (string) $xml->status); + $this->assertGreaterThan(0, (int) $xml->id); + } + + return $response; + } + + /** + * @depends testBulkCreate + * + * @param \SimpleXMLElement[] $createdRecords + */ + public function testBulkDelete(array $createdRecords) + { + $createdRecordIds = array_map(function ($record) { + return (int) $record->id; + }, $createdRecords); + + $response = static::$client->dns()->bulkDelete($createdRecordIds); + + $this->assertCount(3, $response); + + foreach ($response as $xml) { + $this->assertEquals('ok', (string) $xml->status); + $this->assertGreaterThan(0, (int) $xml->id); + } } public function testGetById() { - $dns = static::$_client->dns()->create([ - 'site-id' => static::$_webspace->id, + $dns = static::$client->dns()->create([ + 'site-id' => static::$webspace->id, 'type' => 'TXT', 'host' => '', - 'value' => 'value' + 'value' => 'value', ]); - $dnsInfo = static::$_client->dns()->get('id', $dns->id); + $dnsInfo = static::$client->dns()->get('id', $dns->id); $this->assertEquals('TXT', $dnsInfo->type); - $this->assertEquals(static::$_webspace->id, $dnsInfo->siteId); + $this->assertEquals(static::$webspace->id, $dnsInfo->siteId); $this->assertEquals('value', $dnsInfo->value); - static::$_client->dns()->delete('id', $dns->id); + static::$client->dns()->delete('id', $dns->id); } public function testGetAllByWebspaceId() { - $dns = static::$_client->dns()->create([ - 'site-id' => static::$_webspace->id, + $dns = static::$client->dns()->create([ + 'site-id' => static::$webspace->id, 'type' => 'DS', - 'host' => '', - 'value' => '60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118' + 'host' => 'host', + 'value' => '60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292118', ]); - $dns2 = static::$_client->dns()->create([ - 'site-id' => static::$_webspace->id, + $dns2 = static::$client->dns()->create([ + 'site-id' => static::$webspace->id, 'type' => 'DS', - 'host' => '', - 'value' => '60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292119' + 'host' => 'host', + 'value' => '60485 5 1 2BB183AF5F22588179A53B0A98631FAD1A292119', ]); - $dnsInfo = static::$_client->dns()->getAll('site-id', static::$_webspace->id); + $dnsInfo = static::$client->dns()->getAll('site-id', static::$webspace->id); $dsRecords = []; foreach ($dnsInfo as $dnsRec) { - if ('DS' == $dnsRec->type ) { + if ('DS' == $dnsRec->type) { $dsRecords[] = $dnsRec; } } $this->assertEquals(2, count($dsRecords)); foreach ($dsRecords as $dsRecord) { - $this->assertEquals(static::$_webspace->id, $dsRecord->siteId); + $this->assertEquals(static::$webspace->id, $dsRecord->siteId); } - static::$_client->dns()->delete('id', $dns->id); - static::$_client->dns()->delete('id', $dns2->id); + static::$client->dns()->delete('id', $dns->id); + static::$client->dns()->delete('id', $dns2->id); } public function testDelete() { - $dns = static::$_client->dns()->create([ - 'site-id' => static::$_webspace->id, + $dns = static::$client->dns()->create([ + 'site-id' => static::$webspace->id, 'type' => 'TXT', 'host' => 'host', - 'value' => 'value' + 'value' => 'value', ]); - $result = static::$_client->dns()->delete('id', $dns->id); + $result = static::$client->dns()->delete('id', $dns->id); $this->assertTrue($result); } } diff --git a/tests/EventLogTest.php b/tests/EventLogTest.php index eb350076..2e53f361 100644 --- a/tests/EventLogTest.php +++ b/tests/EventLogTest.php @@ -1,12 +1,13 @@ eventLog()->get(); + $events = static::$client->eventLog()->get(); $this->assertGreaterThan(0, $events); $event = reset($events); @@ -15,18 +16,16 @@ public function testGet() public function testGetDetailedLog() { - $events = static::$_client->eventLog()->getDetailedLog(); + $events = static::$client->eventLog()->getDetailedLog(); $this->assertGreaterThan(0, $events); $event = reset($events); $this->assertGreaterThan(0, $event->time); - $this->assertGreaterThan(0, strlen($event->user)); } public function testGetLastId() { - $lastId = static::$_client->eventLog()->getLastId(); + $lastId = static::$client->eventLog()->getLastId(); $this->assertGreaterThan(0, $lastId); } - } diff --git a/tests/IpTest.php b/tests/IpTest.php index d9cab6bb..e63adef1 100644 --- a/tests/IpTest.php +++ b/tests/IpTest.php @@ -1,16 +1,16 @@ ip()->get(); + $ips = static::$client->ip()->get(); $this->assertGreaterThan(0, count($ips)); $ip = reset($ips); - $this->assertRegExp('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip->ipAddress); + $this->assertMatchesRegularExpression('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $ip->ipAddress); } - } diff --git a/tests/LocaleTest.php b/tests/LocaleTest.php index 739217c8..a4f157de 100644 --- a/tests/LocaleTest.php +++ b/tests/LocaleTest.php @@ -1,12 +1,13 @@ locale()->get(); + $locales = static::$client->locale()->get(); $this->assertGreaterThan(0, count($locales)); $locale = $locales['en-US']; @@ -15,8 +16,7 @@ public function testGet() public function testGetById() { - $locale = static::$_client->locale()->get('en-US'); + $locale = static::$client->locale()->get('en-US'); $this->assertEquals('en-US', $locale->id); } - } diff --git a/tests/MailTest.php b/tests/MailTest.php index d4213fda..242d3dc2 100644 --- a/tests/MailTest.php +++ b/tests/MailTest.php @@ -1,61 +1,136 @@ server()->getServiceStates(); - static::$_isMailSupported = $serviceStates['smtp'] && ('running' == $serviceStates['smtp']['state']); - - static::$_webspace = static::_createWebspace('example.dom'); - } + $serviceStates = static::$client->server()->getServiceStates(); + static::$isMailSupported = isset($serviceStates['smtp']) && ('running' == $serviceStates['smtp']['state']); - public static function tearDownAfterClass() - { - parent::tearDownAfterClass(); - static::$_client->webspace()->delete('id', static::$_webspace->id); + if (static::$isMailSupported) { + static::$webspace = static::createWebspace(); + } } - protected function setUp() + protected function setUp(): void { parent::setUp(); - if (!static::$_isMailSupported) { + if (!static::$isMailSupported) { $this->markTestSkipped('Mail system is not supported.'); } } public function testCreate() { - $mailname = static::$_client->mail()->create('test', static::$_webspace->id, true, 'secret'); + $mailname = static::$client->mail()->create( + 'test', + static::$webspace->id, + true, + PasswordProvider::STRONG_PASSWORD + ); - $this->assertInternalType('integer', $mailname->id); + $this->assertIsInt($mailname->id); $this->assertGreaterThan(0, $mailname->id); $this->assertEquals('test', $mailname->name); - static::$_client->mail()->delete('name', $mailname->name, static::$_webspace->id); + static::$client->mail()->delete('name', $mailname->name, static::$webspace->id); + } + + public function testCreateMultiForwarding() + { + $mailname = static::$client->request([ + 'mail' => [ + 'create' => [ + 'filter' => [ + 'site-id' => static::$webspace->id, + 'mailname' => [ + 'name' => 'test', + 'mailbox' => [ + 'enabled' => true, + ], + 'forwarding' => [ + 'enabled' => true, + 'address' => [ + 'user1@example.com', + 'user2@example.com', + ], + ], + 'alias' => [ + 'test1', + 'test2', + ], + 'password' => [ + 'value' => PasswordProvider::STRONG_PASSWORD, + ], + ], + ], + ], + ], + ]); + + $mailnameInfo = static::$client->request([ + 'mail' => [ + 'get_info' => [ + 'filter' => [ + 'site-id' => static::$webspace->id, + 'name' => 'test', + ], + 'forwarding' => null, + 'aliases' => null, + ], + ], + ]); + + $this->assertSame(2, count($mailnameInfo->mailname->forwarding->address)); + $this->assertSame(2, count($mailnameInfo->mailname->alias)); + + static::$client->mail()->delete('name', 'test', static::$webspace->id); } public function testDelete() { - $mailname = static::$_client->mail()->create('test', static::$_webspace->id); + $mailname = static::$client->mail()->create('test', static::$webspace->id); - $result = static::$_client->mail()->delete('name', $mailname->name, static::$_webspace->id); + $result = static::$client->mail()->delete('name', $mailname->name, static::$webspace->id); $this->assertTrue($result); } + public function testGet() + { + $mailname = static::$client->mail()->create('test', static::$webspace->id); + + $mailnameInfo = static::$client->mail()->get('test', static::$webspace->id); + $this->assertEquals('test', $mailnameInfo->name); + $this->assertEquals($mailname->id, $mailnameInfo->id); + + static::$client->mail()->delete('name', $mailname->name, static::$webspace->id); + } + + public function testGetAll() + { + $mailname = static::$client->mail()->create('test', static::$webspace->id); + + $mailnamesInfo = static::$client->mail()->getAll(static::$webspace->id); + $this->assertCount(1, $mailnamesInfo); + $this->assertEquals('test', $mailnamesInfo[0]->name); + + static::$client->mail()->delete('name', $mailname->name, static::$webspace->id); + } + + public function testGetAllWithoutMailnames() + { + $mailnamesInfo = static::$client->mail()->getAll(static::$webspace->id); + $this->assertCount(0, $mailnamesInfo); + } } diff --git a/tests/PhpHandlerTest.php b/tests/PhpHandlerTest.php new file mode 100644 index 00000000..21f91046 --- /dev/null +++ b/tests/PhpHandlerTest.php @@ -0,0 +1,35 @@ +phpHandler()->get(); + + $this->assertTrue(property_exists($handler, 'type')); + } + + public function testGetAll() + { + $handlers = static::$client->phpHandler()->getAll(); + + $this->assertIsArray($handlers); + $this->assertNotEmpty($handlers); + + $handler = current($handlers); + + $this->assertIsObject($handler); + $this->assertTrue(property_exists($handler, 'type')); + } + + public function testGetUnknownHandlerThrowsException() + { + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionMessage('Php handler does not exists'); + + static::$client->phpHandler()->get('id', 'this-handler-does-not-exist'); + } +} diff --git a/tests/ProtectedDirectoryTest.php b/tests/ProtectedDirectoryTest.php new file mode 100644 index 00000000..17cab77e --- /dev/null +++ b/tests/ProtectedDirectoryTest.php @@ -0,0 +1,91 @@ +protectedDirectory()->add('/', static::$webspace->id); + + $this->assertIsObject($protectedDirectory); + $this->assertGreaterThan(0, $protectedDirectory->id); + + static::$client->protectedDirectory()->delete('id', $protectedDirectory->id); + } + + public function testAddInvalidDirectory() + { + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1019); + + static::$client->protectedDirectory()->add('', static::$webspace->id); + } + + public function testDelete() + { + $protectedDirectory = static::$client->protectedDirectory()->add('/', static::$webspace->id); + + $result = static::$client->protectedDirectory()->delete('id', $protectedDirectory->id); + $this->assertTrue($result); + } + + public function testGetById() + { + $protectedDirectory = static::$client->protectedDirectory()->add('test', static::$webspace->id); + + $foundDirectory = static::$client->protectedDirectory()->get('id', $protectedDirectory->id); + $this->assertEquals('test', $foundDirectory->name); + + static::$client->protectedDirectory()->delete('id', $protectedDirectory->id); + } + + public function testGetUnknownDirectory() + { + $this->expectException(\PleskX\Api\Exception::class); + $this->expectExceptionCode(1013); + + $nonExistentDirectoryId = 99999999; + static::$client->protectedDirectory()->get('id', $nonExistentDirectoryId); + } + + public function testAddUser() + { + $protectedDirectory = static::$client->protectedDirectory()->add('/', static::$webspace->id); + + $user = static::$client->protectedDirectory()->addUser( + $protectedDirectory, + 'john', + PasswordProvider::STRONG_PASSWORD + ); + $this->assertGreaterThan(0, $user->id); + + static::$client->protectedDirectory()->delete('id', $protectedDirectory->id); + } + + public function testDeleteUser() + { + $protectedDirectory = static::$client->protectedDirectory()->add('/', static::$webspace->id); + + $user = static::$client->protectedDirectory()->addUser( + $protectedDirectory, + 'john', + PasswordProvider::STRONG_PASSWORD + ); + $result = static::$client->protectedDirectory()->deleteUser('id', $user->id); + $this->assertTrue($result); + + static::$client->protectedDirectory()->delete('id', $protectedDirectory->id); + } +} diff --git a/tests/ResellerTest.php b/tests/ResellerTest.php index f59f61d8..d1bb87dc 100644 --- a/tests/ResellerTest.php +++ b/tests/ResellerTest.php @@ -1,62 +1,83 @@ 'John Reseller', - 'login' => 'reseller-unit-test', - 'passwd' => 'simple-password', - ]; + public function setUp(): void + { + $this->resellerProperties = [ + 'pname' => 'John Reseller', + 'login' => 'reseller-unit-test', + 'passwd' => PasswordProvider::STRONG_PASSWORD, + ]; + } public function testCreate() { - $reseller = static::$_client->reseller()->create($this->_resellerProperties); - $this->assertInternalType('integer', $reseller->id); + $reseller = static::$client->reseller()->create($this->resellerProperties); + $this->assertIsInt($reseller->id); $this->assertGreaterThan(0, $reseller->id); - static::$_client->reseller()->delete('id', $reseller->id); + static::$client->reseller()->delete('id', $reseller->id); } public function testDelete() { - $reseller = static::$_client->reseller()->create($this->_resellerProperties); - $result = static::$_client->reseller()->delete('id', $reseller->id); + $reseller = static::$client->reseller()->create($this->resellerProperties); + $result = static::$client->reseller()->delete('id', $reseller->id); $this->assertTrue($result); } public function testGet() { - $reseller = static::$_client->reseller()->create($this->_resellerProperties); - $resellerInfo = static::$_client->reseller()->get('id', $reseller->id); + $reseller = static::$client->reseller()->create($this->resellerProperties); + $resellerInfo = static::$client->reseller()->get('id', $reseller->id); $this->assertEquals('John Reseller', $resellerInfo->personalName); $this->assertEquals('reseller-unit-test', $resellerInfo->login); $this->assertGreaterThan(0, count($resellerInfo->permissions)); + $this->assertEquals($reseller->id, $resellerInfo->id); - static::$_client->reseller()->delete('id', $reseller->id); + static::$client->reseller()->delete('id', $reseller->id); } public function testGetAll() { - static::$_client->reseller()->create([ + $keyInfo = static::$client->server()->getKeyInfo(); + + if (!KeyLimitChecker::checkByType($keyInfo, KeyLimitChecker::LIMIT_RESELLERS, 2)) { + $this->markTestSkipped('License does not allow to create more than 1 reseller.'); + } + + static::$client->reseller()->create([ 'pname' => 'John Reseller', 'login' => 'reseller-a', - 'passwd' => 'simple-password', + 'passwd' => PasswordProvider::STRONG_PASSWORD, ]); - static::$_client->reseller()->create([ + static::$client->reseller()->create([ 'pname' => 'Mike Reseller', 'login' => 'reseller-b', - 'passwd' => 'simple-password', + 'passwd' => PasswordProvider::STRONG_PASSWORD, ]); - $resellersInfo = static::$_client->reseller()->getAll(); + $resellersInfo = static::$client->reseller()->getAll(); $this->assertCount(2, $resellersInfo); $this->assertEquals('John Reseller', $resellersInfo[0]->personalName); $this->assertEquals('reseller-a', $resellersInfo[0]->login); - static::$_client->reseller()->delete('login', 'reseller-a'); - static::$_client->reseller()->delete('login', 'reseller-b'); + static::$client->reseller()->delete('login', 'reseller-a'); + static::$client->reseller()->delete('login', 'reseller-b'); } + public function testGetAllEmpty() + { + $resellersInfo = static::$client->reseller()->getAll(); + $this->assertCount(0, $resellersInfo); + } } diff --git a/tests/SecretKeyTest.php b/tests/SecretKeyTest.php index a6bef2ca..1bfc2d6b 100644 --- a/tests/SecretKeyTest.php +++ b/tests/SecretKeyTest.php @@ -1,50 +1,88 @@ secretKey()->create('192.168.0.1'); - $this->assertRegExp('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', $keyId); - static::$_client->secretKey()->delete($keyId); + $keyId = static::$client->secretKey()->create('192.168.0.1'); + $this->assertMatchesRegularExpression( + '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', + $keyId + ); + static::$client->secretKey()->delete($keyId); + } + + public function testCreateAutoIp() + { + $keyId = static::$client->secretKey()->create(); + $this->assertNotEmpty($keyId); + static::$client->secretKey()->delete($keyId); + } + + public function testCreateMultiIps() + { + $keyId = static::$client->secretKey()->create(join(',', ['192.168.0.1', '192.168.0.2'])); + $this->assertMatchesRegularExpression( + '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', + $keyId + ); + static::$client->secretKey()->delete($keyId); + } + + public function testCreateWithDescription() + { + $keyId = static::$client->secretKey()->create('192.168.0.1', 'test key'); + $keyInfo = static::$client->secretKey()->get($keyId); + + $this->assertEquals('test key', $keyInfo->description); + + static::$client->secretKey()->delete($keyId); } public function testGet() { - $keyId = static::$_client->secretKey()->create('192.168.0.1'); - $keyInfo = static::$_client->secretKey()->get($keyId); + $keyId = static::$client->secretKey()->create('192.168.0.1'); + $keyInfo = static::$client->secretKey()->get($keyId); - $this->assertEquals($keyId, $keyInfo->key); + $this->assertNotEmpty($keyInfo->key); $this->assertEquals('192.168.0.1', $keyInfo->ipAddress); $this->assertEquals('admin', $keyInfo->login); - static::$_client->secretKey()->delete($keyId); + static::$client->secretKey()->delete($keyId); } public function testGetAll() { $keyIds = []; - $keyIds[] = static::$_client->secretKey()->create('192.168.0.1'); - $keyIds[] = static::$_client->secretKey()->create('192.168.0.2'); + $keyIds[] = static::$client->secretKey()->create('192.168.0.1'); + $keyIds[] = static::$client->secretKey()->create('192.168.0.2'); - $keys = static::$_client->secretKey()->getAll(); + $keys = static::$client->secretKey()->getAll(); $this->assertGreaterThanOrEqual(2, count($keys)); - $this->assertEquals('192.168.0.1', $keys[0]->ipAddress); + + $keyIpAddresses = array_map(function ($key) { + return $key->ipAddress; + }, $keys); + $this->assertContains('192.168.0.1', $keyIpAddresses); + $this->assertContains('192.168.0.2', $keyIpAddresses); foreach ($keyIds as $keyId) { - static::$_client->secretKey()->delete($keyId); + static::$client->secretKey()->delete($keyId); } } public function testDelete() { - $keyId = static::$_client->secretKey()->create('192.168.0.1'); - static::$_client->secretKey()->delete($keyId); + $keyId = static::$client->secretKey()->create('192.168.0.1'); + static::$client->secretKey()->delete($keyId); try { - static::$_client->secretKey()->get($keyId); + static::$client->secretKey()->get($keyId); $this->fail("Secret key $keyId was not deleted."); } catch (Exception $exception) { $this->assertEquals(1013, $exception->getCode()); @@ -53,12 +91,12 @@ public function testDelete() public function testListEmpty() { - $keys = static::$_client->secretKey()->getAll(); + $keys = static::$client->secretKey()->getAll(); foreach ($keys as $key) { - static::$_client->secretKey()->delete($key->key); + static::$client->secretKey()->delete($key->key); } - $keys = static::$_client->secretKey()->getAll(); + $keys = static::$client->secretKey()->getAll(); $this->assertEquals(0, count($keys)); } } diff --git a/tests/ServerTest.php b/tests/ServerTest.php index 19e40f51..3fe14a0d 100644 --- a/tests/ServerTest.php +++ b/tests/ServerTest.php @@ -1,43 +1,47 @@ server()->getProtos(); - $this->assertInternalType('array', $protos); + $protos = static::$client->server()->getProtos(); + $this->assertIsArray($protos); $this->assertContains('1.6.3.0', $protos); } public function testGetGenInfo() { - $generalInfo = static::$_client->server()->getGeneralInfo(); + $generalInfo = static::$client->server()->getGeneralInfo(); $this->assertGreaterThan(0, strlen($generalInfo->serverName)); - $this->assertRegExp('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', $generalInfo->serverGuid); + $this->assertMatchesRegularExpression( + '/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/', + strtolower($generalInfo->serverGuid) + ); $this->assertEquals('standard', $generalInfo->mode); } public function testGetPreferences() { - $preferences = static::$_client->server()->getPreferences(); - $this->assertInternalType('integer', $preferences->statTtl); + $preferences = static::$client->server()->getPreferences(); + $this->assertIsNumeric($preferences->statTtl); $this->assertGreaterThan(0, $preferences->statTtl); $this->assertEquals(0, $preferences->restartApacheInterval); } public function testGetAdmin() { - $admin = static::$_client->server()->getAdmin(); + $admin = static::$client->server()->getAdmin(); $this->assertGreaterThan(0, strlen($admin->name)); - $this->assertContains('@', $admin->email); + $this->assertStringContainsString('@', $admin->email); } public function testGetKeyInfo() { - $keyInfo = static::$_client->server()->getKeyInfo(); - $this->assertInternalType('array', $keyInfo); + $keyInfo = static::$client->server()->getKeyInfo(); + $this->assertIsArray($keyInfo); $this->assertGreaterThan(0, count($keyInfo)); $this->assertArrayHasKey('plesk_key_id', $keyInfo); $this->assertArrayHasKey('lim_date', $keyInfo); @@ -45,72 +49,77 @@ public function testGetKeyInfo() public function testGetComponents() { - $components = static::$_client->server()->getComponents(); - $this->assertInternalType('array', $components); + $components = static::$client->server()->getComponents(); + $this->assertIsArray($components); $this->assertGreaterThan(0, count($components)); $this->assertArrayHasKey('psa', $components); - $this->assertArrayHasKey('php', $components); } public function testGetServiceStates() { - $serviceStates = static::$_client->server()->getServiceStates(); - $this->assertInternalType('array', $serviceStates); + $serviceStates = static::$client->server()->getServiceStates(); + + $this->assertIsArray($serviceStates); $this->assertGreaterThan(0, count($serviceStates)); - $this->assertArrayHasKey('web', $serviceStates); - - $webService = $serviceStates['web']; - $this->assertInternalType('array', $webService); - $this->assertArrayHasKey('id', $webService); - $this->assertArrayHasKey('title', $webService); - $this->assertArrayHasKey('state', $webService); - $this->assertEquals('running', $webService['state']); + + $service = current($serviceStates); + $this->assertIsArray($service); + $this->assertArrayHasKey('id', $service); + $this->assertArrayHasKey('title', $service); + $this->assertArrayHasKey('state', $service); } public function testGetSessionPreferences() { - $preferences = static::$_client->server()->getSessionPreferences(); - $this->assertInternalType('integer', $preferences->loginTimeout); + $preferences = static::$client->server()->getSessionPreferences(); + $this->assertIsNumeric($preferences->loginTimeout); $this->assertGreaterThan(0, $preferences->loginTimeout); } public function testGetShells() { - $shells = static::$_client->server()->getShells(); - $this->assertInternalType('array', $shells); - $this->assertGreaterThan(0, count($shells)); - $this->assertArrayHasKey('/bin/bash', $shells); + $shells = static::$client->server()->getShells(); - $bash = $shells['/bin/bash']; - $this->assertEquals('/bin/bash', $bash); + $this->assertIsArray($shells); + $this->assertGreaterThan(0, count($shells)); } public function testGetNetworkInterfaces() { - $netInterfaces = static::$_client->server()->getNetworkInterfaces(); - $this->assertInternalType('array', $netInterfaces); + $netInterfaces = static::$client->server()->getNetworkInterfaces(); + $this->assertIsArray($netInterfaces); $this->assertGreaterThan(0, count($netInterfaces)); } public function testGetStatistics() { - $stats = static::$_client->server()->getStatistics(); - $this->assertInternalType('integer', $stats->objects->clients); + $stats = static::$client->server()->getStatistics(); + $this->assertIsNumeric($stats->objects->clients); + $this->assertIsNumeric($stats->objects->domains); + $this->assertIsNumeric($stats->objects->databases); $this->assertEquals('psa', $stats->version->internalName); + $this->assertNotEmpty($stats->version->osName); + $this->assertNotEmpty($stats->version->osVersion); + $this->assertGreaterThan(0, $stats->other->uptime); + $this->assertGreaterThan(0, strlen($stats->other->cpu)); + $this->assertIsFloat($stats->loadAverage->load1min); + $this->assertGreaterThan(0, $stats->memory->total); + $this->assertGreaterThan($stats->memory->free, $stats->memory->total); + $this->assertIsNumeric($stats->swap->total); + $this->assertIsArray($stats->diskSpace); } public function testGetSiteIsolationConfig() { - $config = static::$_client->server()->getSiteIsolationConfig(); - $this->assertInternalType('array', $config); + $config = static::$client->server()->getSiteIsolationConfig(); + $this->assertIsArray($config); $this->assertGreaterThan(0, count($config)); $this->assertArrayHasKey('php', $config); } public function testGetUpdatesInfo() { - $updatesInfo = static::$_client->server()->getUpdatesInfo(); - $this->assertInternalType('boolean', $updatesInfo->installUpdatesAutomatically); + $updatesInfo = static::$client->server()->getUpdatesInfo(); + $this->assertIsBool($updatesInfo->installUpdatesAutomatically); } - } diff --git a/tests/ServicePlanAddonTest.php b/tests/ServicePlanAddonTest.php new file mode 100644 index 00000000..a73022dd --- /dev/null +++ b/tests/ServicePlanAddonTest.php @@ -0,0 +1,62 @@ +servicePlanAddon()->get('id', $servicePlanAddon->id); + + $this->assertNotEmpty($servicePlanAddonInfo->name); + $this->assertSame($servicePlanAddon->id, $servicePlanAddonInfo->id); + } + + public function testGetAll() + { + static::createServicePlanAddon(); + static::createServicePlanAddon(); + static::createServicePlanAddon(); + + $servicePlanAddons = static::$client->servicePlanAddon()->getAll(); + $this->assertIsArray($servicePlanAddons); + $this->assertGreaterThan(2, count($servicePlanAddons)); + $this->assertNotEmpty($servicePlanAddons[0]->name); + } + + public function testCreate() + { + $servicePlanAddon = static::createServicePlanAddon(); + $this->assertGreaterThan(0, $servicePlanAddon->id); + + static::$client->servicePlanAddon()->delete('id', $servicePlanAddon->id); + } + + public function testDelete() + { + $servicePlanAddon = static::createServicePlanAddon(); + $result = static::$client->servicePlanAddon()->delete('id', $servicePlanAddon->id); + + $this->assertTrue($result); + } + + public function testCreateComplex() + { + $properties = [ + 'name' => 'Complex Service Plan Addon', + 'limits' => [ + 'limit' => [ + 'name' => 'disk_space', + 'value' => 1024 * 1024 * 1024, // 1 GB + ], + ], + ]; + + $servicePlanAddon = static::$client->servicePlanAddon()->create($properties); + $this->assertGreaterThan(0, $servicePlanAddon->id); + + static::$client->servicePlanAddon()->delete('id', $servicePlanAddon->id); + } +} diff --git a/tests/ServicePlanTest.php b/tests/ServicePlanTest.php index 196eb280..901a79ba 100644 --- a/tests/ServicePlanTest.php +++ b/tests/ServicePlanTest.php @@ -1,22 +1,80 @@ servicePlan()->get('name', 'Default Domain'); - $this->assertEquals('Default Domain', $servicePlan->name); - $this->assertGreaterThan(0, $servicePlan->id); + $servicePlan = static::createServicePlan(); + $servicePlanInfo = static::$client->servicePlan()->get('id', $servicePlan->id); + $this->assertNotEmpty($servicePlanInfo->name); + $this->assertSame($servicePlan->id, $servicePlanInfo->id); + + static::$client->servicePlan()->delete('id', $servicePlan->id); } public function testGetAll() { - $servicePlans = static::$_client->servicePlan()->getAll(); - $this->assertInternalType('array', $servicePlans); - $this->assertGreaterThan(0, count($servicePlans)); + static::createServicePlan(); + static::createServicePlan(); + static::createServicePlan(); + + $servicePlans = static::$client->servicePlan()->getAll(); + $this->assertIsArray($servicePlans); + $this->assertGreaterThan(2, count($servicePlans)); $this->assertNotEmpty($servicePlans[0]->name); } + public function testCreateServicePlan() + { + $servicePlan = static::createServicePlan(); + $this->assertGreaterThan(0, $servicePlan->id); + + static::$client->servicePlan()->delete('id', $servicePlan->id); + } + + public function testDelete() + { + $servicePlan = static::createServicePlan(); + $result = static::$client->servicePlan()->delete('id', $servicePlan->id); + + $this->assertTrue($result); + } + + public function testCreateComplexServicePlan() + { + $properties = [ + 'name' => 'Complex Service Plan', + 'limits' => [ + 'overuse' => 'block', + 'limit' => [ + 'name' => 'disk_space', + 'value' => 1024 * 1024 * 1024, // 1 GB + ], + ], + 'preferences' => [ + 'stat' => 6, + 'maillists' => 'true', + ], + 'hosting' => [ + 'property' => [ + [ + 'name' => 'ftp_quota', + 'value' => '-1', + ], + [ + 'name' => 'ssl', + 'value' => 'true', + ], + ], + ], + ]; + + $servicePlan = static::$client->servicePlan()->create($properties); + $this->assertGreaterThan(0, $servicePlan->id); + + static::$client->servicePlan()->delete('id', $servicePlan->id); + } } diff --git a/tests/SessionTest.php b/tests/SessionTest.php index 8aabab53..b9d2b841 100644 --- a/tests/SessionTest.php +++ b/tests/SessionTest.php @@ -1,13 +1,22 @@ session()->create('admin', '127.0.0.1'); + + $this->assertIsString($sessionToken); + $this->assertGreaterThan(10, strlen($sessionToken)); + } public function testGet() { - $sessionId = static::$_client->server()->createSession('admin', '127.0.0.1'); - $sessions = static::$_client->session()->get(); + $sessionId = static::$client->server()->createSession('admin', '127.0.0.1'); + $sessions = static::$client->session()->get(); $this->assertArrayHasKey($sessionId, $sessions); $sessionInfo = $sessions[$sessionId]; @@ -18,10 +27,9 @@ public function testGet() public function testTerminate() { - $sessionId = static::$_client->server()->createSession('admin', '127.0.0.1'); - static::$_client->session()->terminate($sessionId); - $sessions = static::$_client->session()->get(); + $sessionId = static::$client->server()->createSession('admin', '127.0.0.1'); + static::$client->session()->terminate($sessionId); + $sessions = static::$client->session()->get(); $this->assertArrayNotHasKey($sessionId, $sessions); } - } diff --git a/tests/SiteAliasTest.php b/tests/SiteAliasTest.php new file mode 100644 index 00000000..c0b2d7e4 --- /dev/null +++ b/tests/SiteAliasTest.php @@ -0,0 +1,70 @@ + $name, + 'site-id' => static::$webspace->id, + ], $properties); + + return static::$client->siteAlias()->create($properties); + } + + public function testCreate() + { + $siteAlias = $this->createSiteAlias('alias.dom'); + + $this->assertIsNumeric($siteAlias->id); + $this->assertGreaterThan(0, $siteAlias->id); + + static::$client->siteAlias()->delete('id', $siteAlias->id); + } + + public function testDelete() + { + $siteAlias = $this->createSiteAlias('alias.dom'); + + $result = static::$client->siteAlias()->delete('id', $siteAlias->id); + $this->assertTrue($result); + } + + public function testGet() + { + $siteAlias = $this->createSiteAlias('alias.dom'); + + $siteAliasInfo = static::$client->siteAlias()->get('id', $siteAlias->id); + $this->assertEquals('alias.dom', $siteAliasInfo->name); + + static::$client->siteAlias()->delete('id', $siteAlias->id); + } + + public function testGetAll() + { + $siteAlias = $this->createSiteAlias('alias.dom'); + $siteAlias2 = $this->createSiteAlias('alias2.dom'); + + $siteAliasInfo = static::$client->siteAlias()->get('id', $siteAlias->id); + $this->assertEquals('alias.dom', $siteAliasInfo->name); + + $siteAliasesInfo = static::$client->siteAlias()->getAll('site-id', self::$webspace->id); + $this->assertCount(2, $siteAliasesInfo); + $this->assertEquals('alias.dom', $siteAliasesInfo[0]->name); + $this->assertEquals('alias.dom', $siteAliasesInfo[0]->asciiName); + + static::$client->siteAlias()->delete('id', $siteAlias->id); + static::$client->siteAlias()->delete('id', $siteAlias2->id); + } +} diff --git a/tests/SiteTest.php b/tests/SiteTest.php old mode 100755 new mode 100644 index 9205cf92..dfaa6fe1 --- a/tests/SiteTest.php +++ b/tests/SiteTest.php @@ -1,100 +1,122 @@ webspace()->delete('id', static::$_webspace->id); + parent::setUp(); + + $keyInfo = static::$client->server()->getKeyInfo(); + + if (!KeyLimitChecker::checkByType($keyInfo, KeyLimitChecker::LIMIT_DOMAINS, 2)) { + $this->markTestSkipped('License does not allow to create more than 1 domain.'); + } } - private function _createSite($name, array $properties = []) + private function createSite($name, array $properties = []): \PleskX\Api\Struct\Site\Info { $properties = array_merge([ 'name' => $name, - 'webspace-id' => static::$_webspace->id, + 'webspace-id' => static::$webspace->id, ], $properties); - return static::$_client->site()->create($properties); + + return static::$client->site()->create($properties); } public function testCreate() { - $site = $this->_createSite('addon.dom'); + $site = $this->createSite('addon.dom'); - $this->assertInternalType('integer', $site->id); + $this->assertIsNumeric($site->id); $this->assertGreaterThan(0, $site->id); - static::$_client->site()->delete('id', $site->id); + static::$client->site()->delete('id', $site->id); } public function testDelete() { - $site = $this->_createSite('addon.dom'); + $site = $this->createSite('addon.dom'); - $result = static::$_client->site()->delete('id', $site->id); + $result = static::$client->site()->delete('id', $site->id); $this->assertTrue($result); } public function testGet() { - $site = $this->_createSite('addon.dom'); + $site = $this->createSite('addon.dom'); - $siteInfo = static::$_client->site()->get('id', $site->id); + $siteInfo = static::$client->site()->get('id', $site->id); $this->assertEquals('addon.dom', $siteInfo->name); + $this->assertMatchesRegularExpression("/^\d{4}-\d{2}-\d{2}$/", $siteInfo->creationDate); + $this->assertEquals(36, strlen($siteInfo->guid)); - static::$_client->site()->delete('id', $site->id); + $siteGuid = $siteInfo->guid; + $siteInfo = static::$client->site()->get('guid', $siteGuid); + $this->assertEquals($site->id, $siteInfo->id); + + static::$client->site()->delete('id', $site->id); + + $siteInfo = static::$client->site()->get('parent-id', static::$webspace->id); + $this->assertNull($siteInfo); } public function testGetHostingWoHosting() { - $site = $this->_createSite('addon.dom'); + $site = $this->createSite('addon.dom'); - $siteHosting = static::$_client->site()->getHosting('id', $site->id); + $siteHosting = static::$client->site()->getHosting('id', $site->id); $this->assertNull($siteHosting); - static::$_client->site()->delete('id', $site->id); + static::$client->site()->delete('id', $site->id); } public function testGetHostingWithHosting() { - $properties = [ + $properties = [ 'hosting' => [ - 'www_root' => 'addon.dom' - ] + 'www_root' => 'addon.dom', + ], ]; - $site = $this->_createSite('addon.dom', $properties); + $site = $this->createSite('addon.dom', $properties); - $siteHosting = static::$_client->site()->getHosting('id', $site->id); + $siteHosting = static::$client->site()->getHosting('id', $site->id); $this->assertArrayHasKey('www_root', $siteHosting->properties); - $this->assertEquals('addon.dom', basename($siteHosting->properties['www_root'])); + $this->assertStringEndsWith('addon.dom', $siteHosting->properties['www_root']); - static::$_client->site()->delete('id', $site->id); + static::$client->site()->delete('id', $site->id); } public function testGetAll() { - $site = $this->_createSite('addon.dom'); - $site2 = $this->_createSite('addon2.dom'); + $site = $this->createSite('addon.dom'); + $site2 = $this->createSite('addon2.dom'); - $sitesInfo = static::$_client->site()->getAll(); + $sitesInfo = static::$client->site()->getAll(); $this->assertCount(2, $sitesInfo); $this->assertEquals('addon.dom', $sitesInfo[0]->name); $this->assertEquals('addon.dom', $sitesInfo[0]->asciiName); + $this->assertEquals($site->id, $sitesInfo[0]->id); - static::$_client->site()->delete('id', $site->id); - static::$_client->site()->delete('id', $site2->id); + static::$client->site()->delete('id', $site->id); + static::$client->site()->delete('id', $site2->id); } + public function testGetAllWithoutSites() + { + $sitesInfo = static::$client->site()->getAll(); + $this->assertEmpty($sitesInfo); + } } diff --git a/tests/SubdomainTest.php b/tests/SubdomainTest.php index 28cdc3ef..db54a110 100644 --- a/tests/SubdomainTest.php +++ b/tests/SubdomainTest.php @@ -1,89 +1,81 @@ webspace()->delete('id', static::$_webspace->id); + static::$webspace = static::createWebspace(); + $webspaceInfo = static::$client->webspace()->get('id', static::$webspace->id); + static::$webspaceName = $webspaceInfo->name; } - /** - * @param string $name - * @param string $webspaceName - * @return \PleskX\Api\Struct\Subdomain\Info - */ - private function _createSubdomain($name) + private function createSubdomain(string $name): \PleskX\Api\Struct\Subdomain\Info { - return static::$_client->subdomain()->create([ - 'parent' => 'example.dom', + return static::$client->subdomain()->create([ + 'parent' => static::$webspaceName, 'name' => $name, 'property' => [ 'www_root' => $name, - ] + ], ]); } public function testCreate() { - $subdomain = $this->_createSubdomain('sub'); + $subdomain = $this->createSubdomain('sub'); - $this->assertInternalType('integer', $subdomain->id); + $this->assertIsInt($subdomain->id); $this->assertGreaterThan(0, $subdomain->id); - static::$_client->subdomain()->delete('id', $subdomain->id); + static::$client->subdomain()->delete('id', $subdomain->id); } public function testDelete() { - $subdomain = $this->_createSubdomain('sub'); + $subdomain = $this->createSubdomain('sub'); - $result = static::$_client->subdomain()->delete('id', $subdomain->id); + $result = static::$client->subdomain()->delete('id', $subdomain->id); $this->assertTrue($result); } public function testGet() { $name = 'sub'; - $subdomain = $this->_createSubdomain($name); + $subdomain = $this->createSubdomain($name); - $subdomainInfo = static::$_client->subdomain()->get('id', $subdomain->id); + $subdomainInfo = static::$client->subdomain()->get('id', $subdomain->id); $this->assertEquals($name . '.' . $subdomainInfo->parent, $subdomainInfo->name); $this->assertTrue(false !== strpos($subdomainInfo->properties['www_root'], $name)); + $this->assertEquals($subdomain->id, $subdomainInfo->id); - static::$_client->subdomain()->delete('id', $subdomain->id); + static::$client->subdomain()->delete('id', $subdomain->id); } public function testGetAll() { $name = 'sub'; $name2 = 'sub2'; - $subdomain = $this->_createSubdomain($name); - $subdomain2 = $this->_createSubdomain($name2); + $subdomain = $this->createSubdomain($name); + $subdomain2 = $this->createSubdomain($name2); - $subdomainsInfo = static::$_client->subdomain()->getAll(); + $subdomainsInfo = static::$client->subdomain()->getAll(); $this->assertCount(2, $subdomainsInfo); $this->assertEquals($name . '.' . $subdomainsInfo[0]->parent, $subdomainsInfo[0]->name); $this->assertTrue(false !== strpos($subdomainsInfo[0]->properties['www_root'], $name)); $this->assertEquals($name2 . '.' . $subdomainsInfo[1]->parent, $subdomainsInfo[1]->name); $this->assertTrue(false !== strpos($subdomainsInfo[1]->properties['www_root'], $name2)); - static::$_client->subdomain()->delete('id', $subdomain->id); - static::$_client->subdomain()->delete('id', $subdomain2->id); + static::$client->subdomain()->delete('id', $subdomain->id); + static::$client->subdomain()->delete('id', $subdomain2->id); - $subdomainsInfo = static::$_client->subdomain()->getAll(); + $subdomainsInfo = static::$client->subdomain()->getAll(); $this->assertEmpty($subdomainsInfo); } } diff --git a/tests/TestCase.php b/tests/TestCase.php deleted file mode 100644 index 2363f507..00000000 --- a/tests/TestCase.php +++ /dev/null @@ -1,52 +0,0 @@ -setCredentials($login, $password); - } - - /** - * @return string - */ - protected static function _getIpAddress() - { - $ips = static::$_client->ip()->get(); - $ipInfo = reset($ips); - return $ipInfo->ipAddress; - } - - /** - * @param string $name - * @return \PleskX\Api\Struct\Webspace\Info - */ - protected static function _createWebspace($name) - { - return static::$_client->webspace()->create([ - 'name' => $name, - 'ip_address' => static::_getIpAddress(), - ], [ - 'ftp_login' => 'test-login', - 'ftp_password' => 'TEST-password', - ]); - } - -} diff --git a/tests/UiTest.php b/tests/UiTest.php index 59a0507b..85e92831 100644 --- a/tests/UiTest.php +++ b/tests/UiTest.php @@ -1,10 +1,11 @@ 'admin', 'url' => 'http://example.com/', 'text' => 'Example site', @@ -12,8 +13,8 @@ class UiTest extends TestCase public function testGetNavigation() { - $navigation = static::$_client->ui()->getNavigation(); - $this->assertInternalType('array', $navigation); + $navigation = static::$client->ui()->getNavigation(); + $this->assertIsArray($navigation); $this->assertGreaterThan(0, count($navigation)); $this->assertArrayHasKey('general', $navigation); $this->assertArrayHasKey('hosting', $navigation); @@ -26,27 +27,26 @@ public function testGetNavigation() public function testCreateCustomButton() { - $buttonId = static::$_client->ui()->createCustomButton('admin', $this->_customButtonProperties); + $buttonId = static::$client->ui()->createCustomButton('admin', $this->customButtonProperties); $this->assertGreaterThan(0, $buttonId); - static::$_client->ui()->deleteCustomButton($buttonId); + static::$client->ui()->deleteCustomButton($buttonId); } public function testGetCustomButton() { - $buttonId = static::$_client->ui()->createCustomButton('admin', $this->_customButtonProperties); - $customButtonInfo = static::$_client->ui()->getCustomButton($buttonId); + $buttonId = static::$client->ui()->createCustomButton('admin', $this->customButtonProperties); + $customButtonInfo = static::$client->ui()->getCustomButton($buttonId); $this->assertEquals('http://example.com/', $customButtonInfo->url); $this->assertEquals('Example site', $customButtonInfo->text); - static::$_client->ui()->deleteCustomButton($buttonId); + static::$client->ui()->deleteCustomButton($buttonId); } public function testDeleteCustomButton() { - $buttonId = static::$_client->ui()->createCustomButton('admin', $this->_customButtonProperties); - $result = static::$_client->ui()->deleteCustomButton($buttonId); + $buttonId = static::$client->ui()->createCustomButton('admin', $this->customButtonProperties); + $result = static::$client->ui()->deleteCustomButton($buttonId); $this->assertTrue($result); } - } diff --git a/tests/Utility/KeyLimitChecker.php b/tests/Utility/KeyLimitChecker.php new file mode 100644 index 00000000..6545ad5c --- /dev/null +++ b/tests/Utility/KeyLimitChecker.php @@ -0,0 +1,46 @@ + $minimalRequirement; + } +} diff --git a/tests/Utility/PasswordProvider.php b/tests/Utility/PasswordProvider.php new file mode 100644 index 00000000..b6e22e33 --- /dev/null +++ b/tests/Utility/PasswordProvider.php @@ -0,0 +1,9 @@ +webspace()->create([ - 'name' => 'example-test.dom', - 'ip_address' => static::_getIpAddress(), - ]); - } +use PleskXTest\Utility\PasswordProvider; +class WebspaceTest extends AbstractTestCase +{ public function testGetPermissionDescriptor() { - $descriptor = static::$_client->webspace()->getPermissionDescriptor(); - $this->assertInternalType('array', $descriptor->permissions); - $this->assertGreaterThan(0, count($descriptor->permissions)); + $descriptor = static::$client->webspace()->getPermissionDescriptor(); + $this->assertIsArray($descriptor->permissions); + $this->assertNotEmpty($descriptor->permissions); } public function testGetLimitDescriptor() { - $descriptor = static::$_client->webspace()->getLimitDescriptor(); - $this->assertInternalType('array', $descriptor->limits); - $this->assertGreaterThan(0, count($descriptor->limits)); + $descriptor = static::$client->webspace()->getLimitDescriptor(); + $this->assertIsArray($descriptor->limits); + $this->assertNotEmpty($descriptor->limits); + } + + public function testGetDiskUsage() + { + $webspace = static::createWebspace(); + $diskusage = static::$client->webspace()->getDiskUsage('id', $webspace->id); + + $this->assertTrue(property_exists($diskusage, 'httpdocs')); + + static::$client->webspace()->delete('id', $webspace->id); } public function testGetPhysicalHostingDescriptor() { - $descriptor = static::$_client->webspace()->getPhysicalHostingDescriptor(); - $this->assertInternalType('array', $descriptor->properties); - $this->assertGreaterThan(0, count($descriptor->properties)); + $descriptor = static::$client->webspace()->getPhysicalHostingDescriptor(); + $this->assertIsArray($descriptor->properties); + $this->assertNotEmpty($descriptor->properties); $ftpLoginProperty = $descriptor->properties['ftp_login']; $this->assertEquals('ftp_login', $ftpLoginProperty->name); $this->assertEquals('string', $ftpLoginProperty->type); } - public function testCreate() + public function testGetPhpSettings() { - $domain = $this->_createDomain(); - $this->assertInternalType('integer', $domain->id); - $this->assertGreaterThan(0, $domain->id); + $webspace = static::createWebspace(); + $info = static::$client->webspace()->getPhpSettings('id', $webspace->id); - static::$_client->webspace()->delete('id', $domain->id); + $this->assertArrayHasKey('open_basedir', $info->properties); + + static::$client->webspace()->delete('id', $webspace->id); + } + + public function testGetLimits() + { + $webspace = static::createWebspace(); + $limits = static::$client->webspace()->getLimits('id', $webspace->id); + + $this->assertIsArray($limits->limits); + $this->assertNotEmpty($limits->limits); + + static::$client->webspace()->delete('id', $webspace->id); } public function testCreateWebspace() { - $webspace = static::$_client->webspace()->create([ - 'name' => 'example-test.dom', - 'ip_address' => static::_getIpAddress(), - ], [ - 'ftp_login' => 'test-login', - 'ftp_password' => 'test-password', - ]); - static::$_client->webspace()->delete('id', $webspace->id); + $webspace = static::createWebspace(); + + $this->assertGreaterThan(0, $webspace->id); + + static::$client->webspace()->delete('id', $webspace->id); + } + + public function testDelete() + { + $webspace = static::createWebspace(); + $result = static::$client->webspace()->delete('id', $webspace->id); + + $this->assertTrue($result); + } + + public function testDeleteByName() + { + $webspace = static::createWebspace(); + $result = static::$client->webspace()->delete('name', $webspace->name); + + $this->assertTrue($result); } public function testRequestCreateWebspace() { - $webspace = static::$_client->webspace()->request([ + $handlers = static::$client->phpHandler()->getAll(); + $enabledHandlers = array_filter($handlers, function ($handler) { + return $handler->handlerStatus !== 'disabled'; + }); + $this->assertGreaterThan(0, count($enabledHandlers)); + $handler = current($enabledHandlers); + + $request = [ 'add' => [ 'gen_setup' => [ - 'name' => 'example-second-test.dom', + 'name' => 'webspace-test-full.test', 'htype' => 'vrt_hst', 'status' => '0', - 'ip_address' => [static::_getIpAddress()], + 'ip_address' => [static::getIpAddress()], ], 'hosting' => [ 'vrt_hst' => [ 'property' => [ [ 'name' => 'php_handler_id', - 'value' => 'fastcgi', + 'value' => $handler->id, ], [ 'name' => 'ftp_login', - 'value' => 'ftp-login-test-1', + 'value' => 'testuser', ], [ 'name' => 'ftp_password', - 'value' => 'ftp-password-test-1', + 'value' => PasswordProvider::STRONG_PASSWORD, ], ], - 'ip_address' => static::_getIpAddress(), + 'ip_address' => static::getIpAddress(), ], ], 'limits' => [ @@ -129,24 +163,81 @@ public function testRequestCreateWebspace() ], 'plan-name' => 'Unlimited', ], - ]); - static::$_client->webspace()->delete('id', $webspace->id); + ]; + + $webspace = static::$client->webspace()->request($request); + + $this->assertGreaterThan(0, $webspace->id); + + static::$client->webspace()->delete('id', $webspace->id); } - public function testDelete() + public function testGet() { - $domain = $this->_createDomain(); - $result = static::$_client->webspace()->delete('id', $domain->id); - $this->assertTrue($result); + $webspace = static::createWebspace(); + $webspaceInfo = static::$client->webspace()->get('id', $webspace->id); + + $this->assertNotEmpty($webspaceInfo->name); + $this->assertEquals(0, $webspaceInfo->realSize); + $this->assertEquals($webspaceInfo->name, $webspaceInfo->asciiName); + $this->assertIsArray($webspaceInfo->ipAddresses); + $this->assertEquals(36, strlen($webspaceInfo->guid)); + $this->assertMatchesRegularExpression("/^\d{4}-\d{2}-\d{2}$/", $webspaceInfo->creationDate); + $this->assertEquals($webspace->id, $webspaceInfo->id); + + static::$client->webspace()->delete('id', $webspace->id); } - public function testGet() + public function testEnable() + { + $webspace = static::createWebspace(); + + static::$client->webspace()->disable('id', $webspace->id); + static::$client->webspace()->enable('id', $webspace->id); + $webspaceInfo = static::$client->webspace()->get('id', $webspace->id); + $this->assertTrue($webspaceInfo->enabled); + + static::$client->webspace()->delete('id', $webspace->id); + } + + public function testDisable() + { + $webspace = static::createWebspace(); + + static::$client->webspace()->disable('id', $webspace->id); + $webspaceInfo = static::$client->webspace()->get('id', $webspace->id); + $this->assertFalse($webspaceInfo->enabled); + + static::$client->webspace()->delete('id', $webspace->id); + } + + public function testSetProperties() { - $domain = $this->_createDomain(); - $domainInfo = static::$_client->webspace()->get('id', $domain->id); - $this->assertEquals('example-test.dom', $domainInfo->name); + $webspace = static::createWebspace(); + static::$client->webspace()->setProperties('id', $webspace->id, [ + 'description' => 'Test Description', + ]); + $webspaceInfo = static::$client->webspace()->get('id', $webspace->id); + $this->assertEquals('Test Description', $webspaceInfo->description); - static::$_client->webspace()->delete('id', $domain->id); + static::$client->webspace()->delete('id', $webspace->id); } + public function testIpsAsArray() + { + $webspace = static::$client->webspace()->create( + [ + 'name' => "test-ips.test", + 'ip_address' => [static::getIpAddress()], + ], + [ + 'ftp_login' => "u-ips", + 'ftp_password' => PasswordProvider::STRONG_PASSWORD, + ] + ); + + $this->assertGreaterThan(0, $webspace->id); + + static::$client->webspace()->delete('id', $webspace->id); + } } diff --git a/tests/autoload.php b/tests/autoload.php deleted file mode 100644 index ac075d33..00000000 --- a/tests/autoload.php +++ /dev/null @@ -1,21 +0,0 @@ -Plesk" > /dev/null + [ $? -eq 0 ] && break + echo "($COUNTER) Waiting for the Plesk initialization..." + sleep 5 + COUNTER=$((COUNTER + 1)) + if [ $COUNTER -eq 60 ]; then + echo "Too long, interrupting..." + break + fi +done