diff --git a/composer.json b/composer.json index deadf449..a525e48b 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,8 @@ "psr/simple-cache": "^1.0", "sabre/cache": "^2.0.1", "naroga/redis-cache": "dev-master", - "aws/aws-sdk-php": "^3.294" + "aws/aws-sdk-php": "^3.294", + "symfony/console": "6.4.x-dev" }, "require-dev" : { diff --git a/composer.lock b/composer.lock index e6714836..d10c5b71 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f414c6453498abc6d6578416a464b7e9", + "content-hash": "cc4804abf9dc372f6dc18abd353bb0e2", "packages": [ { "name": "aws/aws-crt-php", @@ -947,6 +947,60 @@ ], "time": "2023-09-19T16:11:21+00:00" }, + { + "name": "psr/container", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", + "reference": "707984727bd5b2b670e59559d3ed2500240cf875", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "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" + }, + "time": "2023-09-22T11:11:30+00:00" + }, { "name": "psr/http-client", "version": "dev-master", @@ -1583,6 +1637,100 @@ }, "time": "2023-08-17T16:39:06+00:00" }, + { + "name": "symfony/console", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", + "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" + }, + "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/6.4" + }, + "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-12-10T16:15:48+00:00" + }, { "name": "symfony/deprecation-contracts", "version": "dev-main", @@ -1651,6 +1799,256 @@ ], "time": "2024-01-02T14:07:37+00:00" }, + { + "name": "symfony/polyfill-ctype", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "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.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "875e90aeea2777b6f135677f618529449334a612" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "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.28.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": "2023-01-26T09:26:14+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "1.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.28-dev" + }, + "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.28.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": "2023-01-26T09:26:14+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "1.x-dev", @@ -1735,6 +2133,175 @@ ], "time": "2023-07-28T09:04:16+00:00" }, + { + "name": "symfony/service-contracts", + "version": "dev-main", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", + "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^1.1|^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "default-branch": true, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "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": "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/main" + }, + "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-01-02T14:07:37+00:00" + }, + { + "name": "symfony/string", + "version": "6.4.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "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": "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/6.4" + }, + "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-12-10T16:15:48+00:00" + }, { "name": "webonyx/graphql-php", "version": "v15.8.1", @@ -3411,60 +3978,6 @@ }, "time": "2021-02-24T03:25:37+00:00" }, - { - "name": "psr/container", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/php-fig/container.git", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/container/zipball/707984727bd5b2b670e59559d3ed2500240cf875", - "reference": "707984727bd5b2b670e59559d3ed2500240cf875", - "shasum": "" - }, - "require": { - "php": ">=7.4.0" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "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" - }, - "time": "2023-09-22T11:11:30+00:00" - }, { "name": "psr/event-dispatcher", "version": "dev-master", @@ -4537,100 +5050,6 @@ ], "time": "2023-12-31T07:41:08+00:00" }, - { - "name": "symfony/console", - "version": "6.4.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0254811a143e6bc6c8deea08b589a7e68a37f625", - "reference": "0254811a143e6bc6c8deea08b589a7e68a37f625", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" - }, - "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" - }, - "provide": { - "psr/log-implementation": "1.0|2.0|3.0" - }, - "require-dev": { - "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", - "symfony/http-foundation": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" - }, - "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/6.4" - }, - "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-12-10T16:15:48+00:00" - }, { "name": "symfony/event-dispatcher", "version": "6.4.x-dev", @@ -4982,256 +5401,6 @@ ], "time": "2023-08-08T10:16:24+00:00" }, - { - "name": "symfony/polyfill-ctype", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "provide": { - "ext-ctype": "*" - }, - "suggest": { - "ext-ctype": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "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.28.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": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-grapheme", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "875e90aeea2777b6f135677f618529449334a612" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", - "reference": "875e90aeea2777b6f135677f618529449334a612", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "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.28.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": "2023-01-26T09:26:14+00:00" - }, - { - "name": "symfony/polyfill-intl-normalizer", - "version": "1.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "suggest": { - "ext-intl": "For best performance" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.28-dev" - }, - "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.28.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": "2023-01-26T09:26:14+00:00" - }, { "name": "symfony/polyfill-php80", "version": "1.x-dev", @@ -5457,89 +5626,6 @@ ], "time": "2023-12-22T16:42:54+00:00" }, - { - "name": "symfony/service-contracts", - "version": "dev-main", - "source": { - "type": "git", - "url": "https://github.com/symfony/service-contracts.git", - "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", - "reference": "cea2eccfcd27ac3deb252bd67f78b9b8ffc4da84", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/container": "^1.1|^2.0" - }, - "conflict": { - "ext-psr": "<1.1|>=2" - }, - "default-branch": true, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\Service\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "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": "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/main" - }, - "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-01-02T14:07:37+00:00" - }, { "name": "symfony/stopwatch", "version": "6.4.x-dev", @@ -5602,92 +5688,6 @@ ], "time": "2023-02-16T10:14:28+00:00" }, - { - "name": "symfony/string", - "version": "6.4.x-dev", - "source": { - "type": "git", - "url": "https://github.com/symfony/string.git", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "reference": "7cb80bc10bfcdf6b5492741c0b9357dac66940bc", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/polyfill-ctype": "~1.8", - "symfony/polyfill-intl-grapheme": "~1.0", - "symfony/polyfill-intl-normalizer": "~1.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/translation-contracts": "<2.5" - }, - "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", - "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "files": [ - "Resources/functions.php" - ], - "psr-4": { - "Symfony\\Component\\String\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "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": "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/6.4" - }, - "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-12-10T16:15:48+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.2", diff --git a/core/cli_app.php b/core/cli_app.php new file mode 100644 index 00000000..19fdf293 --- /dev/null +++ b/core/cli_app.php @@ -0,0 +1,64 @@ +addOption(new InputOption( + '--user', + '-u', + InputOption::VALUE_NONE, + 'Log in as the given user' + )); + + return $definition; + } + + public function run(InputInterface $input = null, OutputInterface $output = null): int + { + global $user; + + $input ??= new ArgvInput(); + $output ??= new ConsoleOutput(); + + if ($input->hasParameterOption(['--user', '-u'])) { + $user = User::by_name($input->getOption('user')); + if (is_null($user)) { + die("Unknown user"); + } else { + send_event(new UserLoginEvent($user)); + } + } + + $log_level = SCORE_LOG_WARNING; + if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { + $log_level = SCORE_LOG_ERROR; + } else { + if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { + $log_level = SCORE_LOG_DEBUG; + } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { + $log_level = SCORE_LOG_DEBUG; + } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { + $log_level = SCORE_LOG_INFO; + } + } + if (!defined("CLI_LOG_LEVEL")) { + define("CLI_LOG_LEVEL", $log_level); + } + + return parent::run($input, $output); + } +} diff --git a/core/event.php b/core/event.php index 5e8e9936..70c59052 100644 --- a/core/event.php +++ b/core/event.php @@ -200,73 +200,12 @@ class PageRequestEvent extends Event } -/** - * Sent when index.php is called from the command line - */ -class CommandEvent extends Event +class CliGenEvent extends Event { - public string $cmd = "help"; - - /** - * @var string[] - */ - public array $args = []; - - /** - * @param string[] $args - */ - public function __construct(array $args) - { + public function __construct( + public \Symfony\Component\Console\Application $app + ) { parent::__construct(); - global $user; - - $opts = []; - $log_level = SCORE_LOG_WARNING; - $arg_count = count($args); - - for ($i = 1; $i < $arg_count; $i++) { - switch ($args[$i]) { - case '-u': - $user = User::by_name($args[++$i]); - if (is_null($user)) { - die("Unknown user"); - } else { - send_event(new UserLoginEvent($user)); - } - break; - case '-q': - $log_level += 10; - break; - case '-v': - $log_level -= 10; - break; - default: - $opts[] = $args[$i]; - break; - } - } - - if (!defined("CLI_LOG_LEVEL")) { - define("CLI_LOG_LEVEL", $log_level); - } - - if (count($opts) > 0) { - $this->cmd = $opts[0]; - $this->args = array_slice($opts, 1); - } else { - print "\n"; - print "Usage: php {$args[0]} [flags] [command]\n"; - print "\n"; - print "Flags:\n"; - print "\t-u [username]\n"; - print "\t\tLog in as the specified user\n"; - print "\t-q / -v\n"; - print "\t\tBe quieter / more verbose\n"; - print "\t\tScale is debug - info - warning - error - critical\n"; - print "\t\tDefault is to show warnings and above\n"; - print "\n"; - print "Currently known commands:\n"; - } } } diff --git a/ext/admin/main.php b/ext/admin/main.php index 39c314f1..294fd5ac 100644 --- a/ext/admin/main.php +++ b/ext/admin/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + /** * Sent when the admin page is ready to be added to */ @@ -65,67 +69,90 @@ class AdminPage extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tget-page \n"; - print "\t\teg 'get-page post/list'\n\n"; - print "\tpost-page \n"; - print "\t\teg 'post-page ip_ban/delete id=1'\n\n"; - print "\tget-token\n"; - print "\t\tget a CSRF auth token\n\n"; - print "\tregen-thumb \n"; - print "\t\tregenerate a thumbnail\n\n"; - print "\tcache [get|set|del] [key] \n"; - print "\t\teg 'cache get config'\n\n"; - } - if ($event->cmd == "get-page") { - global $page; - $_SERVER['REQUEST_URI'] = $event->args[0]; - if (isset($event->args[1])) { - parse_str($event->args[1], $_GET); - $_SERVER['REQUEST_URI'] .= "?" . $event->args[1]; - } - send_event(new PageRequestEvent("GET", $event->args[0])); - $page->display(); - } - if ($event->cmd == "post-page") { - global $page; - if (isset($event->args[1])) { - parse_str($event->args[1], $_POST); - } - send_event(new PageRequestEvent("POST", $event->args[0])); - $page->display(); - } - if ($event->cmd == "get-token") { - global $user; - print($user->get_auth_token()); - } - if ($event->cmd == "regen-thumb") { - $uid = $event->args[0]; - $image = Image::by_id_or_hash($uid); - if ($image) { - send_event(new ThumbnailGenerationEvent($image, true)); - } else { - print("No post with ID '$uid'\n"); - } - } - if ($event->cmd == "cache") { - global $cache; - $cmd = $event->args[0]; - $key = $event->args[1]; - switch ($cmd) { - case "get": - var_export($cache->get($key)); - break; - case "set": - $cache->set($key, $event->args[2], 60); - break; - case "del": - $cache->delete($key); - break; - } - } + $event->app->register('page:get') + ->addArgument('query', InputArgument::REQUIRED) + ->addArgument('args', InputArgument::OPTIONAL) + ->setDescription('Get a page, eg /post/list') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $page; + $query = $input->getArgument('query'); + $args = $input->getArgument('args'); + $_SERVER['REQUEST_URI'] = $query; + if (!is_null($args)) { + parse_str($args, $_GET); + $_SERVER['REQUEST_URI'] .= "?" . $args; + } + send_event(new PageRequestEvent("GET", $query)); + $page->display(); + return Command::SUCCESS; + }); + $event->app->register('page:post') + ->addArgument('query', InputArgument::REQUIRED) + ->addArgument('args', InputArgument::OPTIONAL) + ->setDescription('Post a page, eg ip_ban/delete id=1') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $page; + $query = $input->getArgument('query'); + $args = $input->getArgument('args'); + global $page; + if (!is_null($args)) { + parse_str($args, $_POST); + } + send_event(new PageRequestEvent("POST", $query)); + $page->display(); + return Command::SUCCESS; + }); + $event->app->register('get-token') + ->setDescription('Get a CSRF token') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $user; + $output->writeln($user->get_auth_token()); + return Command::SUCCESS; + }); + $event->app->register('regen-thumb') + ->addArgument('id_or_hash', InputArgument::REQUIRED) + ->setDescription("Regenerate a post's thumbnail") + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $uid = $input->getArgument('id_or_hash'); + $image = Image::by_id_or_hash($uid); + if ($image) { + send_event(new ThumbnailGenerationEvent($image, true)); + } else { + $output->writeln("No post with ID '$uid'\n"); + } + return Command::SUCCESS; + }); + $event->app->register('cache:get') + ->addArgument('key', InputArgument::REQUIRED) + ->setDescription("Get a cache value") + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $cache; + $key = $input->getArgument('key'); + $output->writeln(var_export($cache->get($key), true)); + return Command::SUCCESS; + }); + $event->app->register('cache:set') + ->addArgument('key', InputArgument::REQUIRED) + ->addArgument('value', InputArgument::REQUIRED) + ->setDescription("Set a cache value") + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $cache; + $key = $input->getArgument('key'); + $value = $input->getArgument('value'); + $cache->set($key, $value, 60); + return Command::SUCCESS; + }); + $event->app->register('cache:del') + ->addArgument('key', InputArgument::REQUIRED) + ->setDescription("Delete a cache value") + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $cache; + $key = $input->getArgument('key'); + $cache->delete($key); + return Command::SUCCESS; + }); } public function onAdminBuilding(AdminBuildingEvent $event) diff --git a/ext/admin/test.php b/ext/admin/test.php index a4cbfcae..3b59bf82 100644 --- a/ext/admin/test.php +++ b/ext/admin/test.php @@ -23,19 +23,4 @@ class AdminPageTest extends ShimmiePHPUnitTestCase $this->assertEquals(200, $page->code); $this->assertEquals("Admin Tools", $page->title); } - - public function testCommands() - { - send_event(new UserLoginEvent(User::by_name(self::$admin_name))); - ob_start(); - send_event(new CommandEvent(["index.php", "help"])); - send_event(new CommandEvent(["index.php", "get-page", "post/list"])); - send_event(new CommandEvent(["index.php", "post-page", "post/list", "foo=bar"])); - send_event(new CommandEvent(["index.php", "get-token"])); - send_event(new CommandEvent(["index.php", "regen-thumb", "42"])); - ob_end_clean(); - - // don't crash - $this->assertTrue(true); - } } diff --git a/ext/bulk_actions/main.php b/ext/bulk_actions/main.php index e296893d..b22d72d0 100644 --- a/ext/bulk_actions/main.php +++ b/ext/bulk_actions/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class BulkActionException extends SCoreException { } @@ -97,22 +101,20 @@ class BulkActions extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tbulk-action \n"; - print "\t\tperform an action on all query results\n\n"; - } - if ($event->cmd == "bulk-action") { - if (count($event->args) < 2) { - return; - } - $action = $event->args[0]; - $query = $event->args[1]; - $items = $this->yield_search_results($query); - log_info("bulk_actions", "Performing $action on {$event->args[1]}"); - send_event(new BulkActionEvent($event->args[0], $items)); - } + $event->app->register('bulk-action') + ->addArgument('action', InputArgument::REQUIRED) + ->addArgument('query', InputArgument::REQUIRED) + ->setDescription('Perform a bulk action on a given query') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $action = $input->getArgument('action'); + $query = $input->getArgument('query'); + $items = $this->yield_search_results($query); + log_info("bulk_actions", "Performing $action on $query"); + send_event(new BulkActionEvent($action, $items)); + return Command::SUCCESS; + }); } public function onBulkAction(BulkActionEvent $event) diff --git a/ext/bulk_add/main.php b/ext/bulk_add/main.php index e3d7fa0c..c6cf8bdb 100644 --- a/ext/bulk_add/main.php +++ b/ext/bulk_add/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class BulkAddEvent extends Event { public string $dir; @@ -35,25 +39,23 @@ class BulkAdd extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tbulk-add [directory]\n"; - print "\t\tImport this directory\n\n"; - } - if ($event->cmd == "bulk-add") { - if (count($event->args) == 1) { - $bae = send_event(new BulkAddEvent($event->args[0])); + $event->app->register('bulk-add') + ->addArgument('directory', InputArgument::REQUIRED) + ->setDescription('Import a directory of images') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $dir = $input->getArgument('directory'); + $bae = send_event(new BulkAddEvent($dir)); foreach ($bae->results as $r) { if(is_a($r, UploadError::class)) { - print($r->name." failed: ".$r->error."\n"); + $output->writeln($r->name." failed: ".$r->error); } else { - print($r->name." ok\n"); + $output->writeln($r->name." ok"); } } - print(implode("\n", $bae->results)); - } - } + return Command::SUCCESS; + }); } public function onAdminBuilding(AdminBuildingEvent $event) diff --git a/ext/bulk_add_csv/main.php b/ext/bulk_add_csv/main.php index 790be05e..aa79255a 100644 --- a/ext/bulk_add_csv/main.php +++ b/ext/bulk_add_csv/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class BulkAddCSV extends Extension { /** @var BulkAddCSVTheme */ @@ -21,23 +25,22 @@ class BulkAddCSV extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tbulk-add-csv [/path/to.csv]\n"; - print "\t\tImport this .csv file (refer to documentation)\n\n"; - } - if ($event->cmd == "bulk-add-csv") { - global $user; + $event->app->register('bulk-add-csv') + ->addArgument('path-to-csv', InputArgument::REQUIRED) + ->setDescription('Import posts from a given CSV file') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $user; + if (!$user->can(Permissions::BULK_ADD)) { + $output->writeln("Not running as an admin, which can cause problems."); + $output->writeln("Please add the parameter: -u admin_username"); + return Command::FAILURE; + } - //Nag until CLI is admin by default - if (!$user->can(Permissions::BULK_ADD)) { - print "Not running as an admin, which can cause problems.\n"; - print "Please add the parameter: -u admin_username"; - } elseif (count($event->args) == 1) { - $this->add_csv($event->args[0]); - } - } + $this->add_csv($input->getArgument('path-to-csv')); + return Command::SUCCESS; + }); } public function onAdminBuilding(AdminBuildingEvent $event) diff --git a/ext/et/main.php b/ext/et/main.php index 7062f797..21bf015f 100644 --- a/ext/et/main.php +++ b/ext/et/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class ET extends Extension { /** @var ETTheme */ @@ -37,15 +41,14 @@ class ET extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tinfo\n"; - print "\t\tList a bunch of info\n\n"; - } - if ($event->cmd == "info") { - print($this->to_yaml($this->get_info())); - } + $event->app->register('info') + ->setDescription('List a bunch of info') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + print($this->to_yaml($this->get_info())); + return Command::SUCCESS; + }); } /** diff --git a/ext/ext_manager/main.php b/ext/ext_manager/main.php index d19e0dde..ac14990f 100644 --- a/ext/ext_manager/main.php +++ b/ext/ext_manager/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class ExtensionAuthor { public string $name; @@ -60,15 +64,14 @@ class ExtManager extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tdisable-all-ext\n"; - print "\t\tdisable all extensions\n\n"; - } - if ($event->cmd == "disable-all-ext") { - $this->write_config([]); - } + $event->app->register('disable-all-ext') + ->setDescription('Disable all extensions') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $this->write_config([]); + return Command::SUCCESS; + }); } public function onPageSubNavBuilding(PageSubNavBuildingEvent $event) diff --git a/ext/graphql/main.php b/ext/graphql/main.php index 2a039bf8..5a5b63b6 100644 --- a/ext/graphql/main.php +++ b/ext/graphql/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + use GraphQL\GraphQL as GQL; use GraphQL\Server\StandardServer; use GraphQL\Error\DebugFlag; @@ -173,29 +177,32 @@ class GraphQL extends Extension return ["image_ids" => array_map(fn ($im) => $im->id, $event->images)]; } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tgraphql \n"; - print "\t\teg 'graphql \"{ post(id: 18) { id, hash } }\"'\n\n"; - print "\tgraphql-schema\n"; - print "\t\tdump the schema\n\n"; - } - if ($event->cmd == "graphql") { - $t1 = ftime(); - $schema = $this->get_schema(); - $t2 = ftime(); - $debug = DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::RETHROW_INTERNAL_EXCEPTIONS; - $body = GQL::executeQuery($schema, $event->args[0])->toArray($debug); - $t3 = ftime(); - $body['stats'] = get_debug_info_arr(); - $body['stats']['graphql_schema_time'] = round($t2 - $t1, 2); - $body['stats']['graphql_execute_time'] = round($t3 - $t2, 2); - echo \json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); - } - if ($event->cmd == "graphql-schema") { - $schema = $this->get_schema(); - echo(SchemaPrinter::doPrint($schema)); - } + $event->app->register('graphql:query') + ->addArgument('query', InputArgument::REQUIRED) + ->setDescription('Run a GraphQL query') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $query = $input->getArgument('query'); + $t1 = ftime(); + $schema = $this->get_schema(); + $t2 = ftime(); + $debug = DebugFlag::INCLUDE_DEBUG_MESSAGE | DebugFlag::RETHROW_INTERNAL_EXCEPTIONS; + $body = GQL::executeQuery($schema, $query)->toArray($debug); + $t3 = ftime(); + $body['stats'] = get_debug_info_arr(); + $body['stats']['graphql_schema_time'] = round($t2 - $t1, 2); + $body['stats']['graphql_execute_time'] = round($t3 - $t2, 2); + echo \json_encode($body, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); + return Command::SUCCESS; + }); + $event->app->register('graphql:schema') + ->addArgument('query', InputArgument::REQUIRED) + ->setDescription('Print out the GraphQL schema') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $schema = $this->get_schema(); + echo(SchemaPrinter::doPrint($schema)); + return Command::SUCCESS; + }); } } diff --git a/ext/image/main.php b/ext/image/main.php index b6a89ded..d2836ed0 100644 --- a/ext/image/main.php +++ b/ext/image/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + require_once "config.php"; /** @@ -118,17 +122,17 @@ class ImageIO extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tdelete \n"; - print "\t\tdelete a specific post\n\n"; - } - if ($event->cmd == "delete") { - $post_id = (int)$event->args[0]; - $image = Image::by_id($post_id); - send_event(new ImageDeletionEvent($image)); - } + $event->app->register('delete') + ->addArgument('id', InputArgument::REQUIRED) + ->setDescription('Delete a specific post') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $post_id = (int)$input->getArgument('id'); + $image = Image::by_id($post_id); + send_event(new ImageDeletionEvent($image)); + return Command::SUCCESS; + }); } public function onImageAddition(ImageAdditionEvent $event) diff --git a/ext/index/main.php b/ext/index/main.php index 8ad07eb4..60010a26 100644 --- a/ext/index/main.php +++ b/ext/index/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + require_once "config.php"; require_once "events.php"; @@ -147,20 +151,19 @@ class Index extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - # TODO: --fields a,b,c - print "\tsearch \n"; - print "\t\tsearch the database and print results\n\n"; - } - if ($event->cmd == "search") { - $query = count($event->args) > 0 ? Tag::explode($event->args[0]) : []; - $items = Search::find_images(limit: 1000, tags: $query); - foreach ($items as $item) { - print("{$item->hash}\n"); - } - } + $event->app->register('search') + ->addArgument('query', InputArgument::REQUIRED) + ->setDescription('Search the database and print results') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $query = Tag::explode($input->getArgument('query')); + $items = Search::find_images(limit: 1000, tags: $query); + foreach ($items as $item) { + $output->writeln($item->hash); + } + return Command::SUCCESS; + }); } public function onSearchTermParse(SearchTermParseEvent $event) diff --git a/ext/media/main.php b/ext/media/main.php index a9bd41cd..81884f75 100644 --- a/ext/media/main.php +++ b/ext/media/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + require_once "config.php"; require_once "events.php"; require_once "media_engine.php"; @@ -147,22 +151,22 @@ class Media extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tmedia-rescan \n"; - print "\t\trefresh metadata for a given post\n\n"; - } - if ($event->cmd == "media-rescan") { - $uid = $event->args[0]; - $image = Image::by_id_or_hash($uid); - if ($image) { - send_event(new MediaCheckPropertiesEvent($image)); - $image->save_to_db(); - } else { - print("No post with ID '$uid'\n"); - } - } + $event->app->register('media-rescan') + ->addArgument('id_or_hash', InputArgument::REQUIRED) + ->setDescription('Refresh metadata for a given post') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $uid = $input->getArgument('id_or_hash'); + $image = Image::by_id_or_hash($uid); + if ($image) { + send_event(new MediaCheckPropertiesEvent($image)); + $image->save_to_db(); + } else { + $output->writeln("No post with ID '$uid'"); + } + return Command::SUCCESS; + }); } /** diff --git a/ext/rule34/main.php b/ext/rule34/main.php index dd9f1193..96508e0d 100644 --- a/ext/rule34/main.php +++ b/ext/rule34/main.php @@ -4,6 +4,11 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; + +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + use function MicroHTML\{emptyHTML, A}; if ( @@ -71,15 +76,20 @@ class Rule34 extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - global $cache; - if ($event->cmd == "wipe-thumb-cache") { - foreach (Search::find_images_iterable(0, null, Tag::explode($event->args[0])) as $image) { - print($image->id . "\n"); - $cache->delete("thumb-block:{$image->id}"); - } - } + $event->app->register('wipe-thumb-cache') + ->addArgument('tags', InputArgument::REQUIRED) + ->setDescription('Delete cached thumbnails for images matching the given tags') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $cache; + $tags = Tag::explode($input->getArgument('tags')); + foreach (Search::find_images_iterable(0, null, $tags) as $image) { + $output->writeln($image->id); + $cache->delete("thumb-block:{$image->id}"); + } + return Command::SUCCESS; + }); } public function onSourceSet(SourceSetEvent $event) diff --git a/ext/s3/main.php b/ext/s3/main.php index 3913c79a..5cc6ba5c 100644 --- a/ext/s3/main.php +++ b/ext/s3/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + use function MicroHTML\INPUT; require_once "config.php"; @@ -37,56 +41,54 @@ class S3 extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - global $database; - if ($event->cmd == "help") { - print "\ts3-sync \n"; - print "\t\tsync a post to s3\n\n"; - print "\ts3-rm \n"; - print "\t\tdelete a leftover file from s3\n\n"; - } - if ($event->cmd == "s3-sync") { - if(count($event->args) == 0) { + $event->app->register('s3:process') + ->setDescription('Process the S3 queue') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $database; $count = $database->get_one("SELECT COUNT(*) FROM s3_sync_queue"); - print("{$count} items in queue\n"); + $output->writeln("{$count} items in queue"); foreach($database->get_all("SELECT * FROM s3_sync_queue ORDER BY time ASC") as $row) { if($row['action'] == "S") { $image = Image::by_hash($row['hash']); - print("SYN {$row['hash']} ($image->id)\n"); + $output->writeln("SYN {$row['hash']} ($image->id)"); $this->sync_post($image); } elseif($row['action'] == "D") { - print("DEL {$row['hash']}\n"); + $output->writeln("DEL {$row['hash']}"); $this->remove_file($row['hash']); } else { - print("??? {$row['hash']} ({$row['action']})\n"); + $output->writeln("??? {$row['hash']} ({$row['action']})"); } } - } else { - if (preg_match('/^(\d+)-(\d+)$/', $event->args[0], $matches)) { - $start = (int)$matches[1]; - $end = (int)$matches[2]; - } else { - $start = (int)$event->args[0]; - $end = $start; - } + return Command::SUCCESS; + }); + $event->app->register('s3:sync') + ->addArgument('start', InputArgument::REQUIRED) + ->addArgument('end', InputArgument::REQUIRED) + ->setDescription('Sync a range of images to S3') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $start = (int)$input->getArgument('start'); + $end = (int)$input->getArgument('end'); + $output->writeln("Syncing range: $start - $end"); foreach(Search::find_images_iterable(tags: ["order=id", "id>=$start", "id<=$end"]) as $image) { if($this->sync_post($image)) { print("{$image->id}: {$image->hash}\n"); } else { print("{$image->id}: {$image->hash} (skipped)\n"); } - ob_flush(); } - } - } - if ($event->cmd == "s3-rm") { - foreach($event->args as $hash) { - print("{$hash}\n"); - ob_flush(); + return Command::SUCCESS; + }); + $event->app->register('s3:rm') + ->addArgument('hash', InputArgument::REQUIRED) + ->setDescription('Delete a leftover file from S3') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $hash = $input->getArgument('hash'); + $output->writeln("Deleting file: '$hash'"); $this->remove_file($hash); - } - } + return Command::SUCCESS; + }); } public function onPageRequest(PageRequestEvent $event) diff --git a/ext/setup/main.php b/ext/setup/main.php index c942644d..4809dd86 100644 --- a/ext/setup/main.php +++ b/ext/setup/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + require_once "config.php"; /* @@ -420,26 +424,26 @@ class Setup extends Extension log_warning("setup", "Cache cleared"); } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tconfig [get|set] \n"; - print "\t\teg 'config get db_version'\n\n"; - } - if ($event->cmd == "config") { - global $cache, $config; - $cmd = $event->args[0]; - $key = $event->args[1]; - switch ($cmd) { - case "get": - print($config->get_string($key) . "\n"); - break; - case "set": - $config->set_string($key, $event->args[2]); - break; - } - $cache->delete("config"); - } + $event->app->register('config:get') + ->addArgument('key', InputArgument::REQUIRED) + ->setDescription('Get a config value') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $config; + $output->writeln($config->get_string($input->getArgument('key'))); + return Command::SUCCESS; + }); + $event->app->register('config:set') + ->addArgument('key', InputArgument::REQUIRED) + ->addArgument('value', InputArgument::REQUIRED) + ->setDescription('Set a config value') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + global $cache, $config; + $config->set_string($input->getArgument('key'), $input->getArgument('value')); + $cache->delete("config"); + return Command::SUCCESS; + }); } public function onPageSubNavBuilding(PageSubNavBuildingEvent $event) diff --git a/ext/tag_edit/main.php b/ext/tag_edit/main.php index 4492e0fb..d1994bb1 100644 --- a/ext/tag_edit/main.php +++ b/ext/tag_edit/main.php @@ -4,6 +4,10 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + /* * OwnerSetEvent: * $image_id @@ -159,19 +163,19 @@ class TagEdit extends Extension } } - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - global $database; - if ($event->cmd == "help") { - print "\ttag-replace \n"; - print "\t\tmass replace tags\n\n"; - } - if ($event->cmd == "tag-replace") { - print("Mass editing tags: '{$event->args[0]}' -> '{$event->args[1]}'\n"); - if(count($event->args) == 2) { - $this->mass_tag_edit($event->args[0], $event->args[1], true); - } - } + $event->app->register('tag-replace') + ->addArgument('old_tag', InputArgument::REQUIRED) + ->addArgument('new_tag', InputArgument::REQUIRED) + ->setDescription('Mass edit tags') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $old_tag = $input->getArgument('old_tag'); + $new_tag = $input->getArgument('new_tag'); + $output->writeln("Mass editing tags: '$old_tag' -> '$new_tag'"); + $this->mass_tag_edit($old_tag, $new_tag, true); + return Command::SUCCESS; + }); } // public function onPostListBuilding(PostListBuildingEvent $event) diff --git a/ext/upgrade/main.php b/ext/upgrade/main.php index 8fb3b655..ff6f1dab 100644 --- a/ext/upgrade/main.php +++ b/ext/upgrade/main.php @@ -4,20 +4,23 @@ declare(strict_types=1); namespace Shimmie2; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\{InputInterface,InputArgument}; +use Symfony\Component\Console\Output\OutputInterface; + class Upgrade extends Extension { - public function onCommand(CommandEvent $event) + public function onCliGen(CliGenEvent $event) { - if ($event->cmd == "help") { - print "\tdb-upgrade\n"; - print "\t\tRun DB schema updates, if automatic updates are disabled\n\n"; - } - if ($event->cmd == "db-upgrade") { - print("Running DB Upgrade\n"); - global $database; - $database->set_timeout(null); // These updates can take a little bit - send_event(new DatabaseUpgradeEvent()); - } + $event->app->register('db-upgrade') + ->setDescription('Run DB schema updates, if automatic updates are disabled') + ->setCode(function (InputInterface $input, OutputInterface $output): int { + $output->writeln("Running DB Upgrade"); + global $database; + $database->set_timeout(null); // These updates can take a little bit + send_event(new DatabaseUpgradeEvent()); + return Command::SUCCESS; + }); } public function onDatabaseUpgrade(DatabaseUpgradeEvent $event) diff --git a/index.php b/index.php index 88018fbb..2ef1d2e8 100644 --- a/index.php +++ b/index.php @@ -82,7 +82,9 @@ try { if (PHP_SAPI === 'cli' || PHP_SAPI == 'phpdbg') { ob_end_flush(); ob_implicit_flush(true); - send_event(new CommandEvent($argv)); + $app = new CliApp(); + send_event(new CliGenEvent($app)); + $app->run(); } else { send_event(new PageRequestEvent($_SERVER['REQUEST_METHOD'], _get_query())); $page->display();