From e893c33f392f30b8ee80d5dfb29abd11e4fddf95 Mon Sep 17 00:00:00 2001 From: "Abdulmhsen B. A. A" Date: Sat, 16 Dec 2023 20:14:19 +0300 Subject: [PATCH] Added Interactive shell. --- composer.json | 3 +- composer.lock | 376 ++++++++++++++++---------- src/Commands/System/TinkerCommand.php | 98 +++++++ 3 files changed, 328 insertions(+), 149 deletions(-) create mode 100644 src/Commands/System/TinkerCommand.php diff --git a/composer.json b/composer.json index faf12a58..56de729d 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,8 @@ "nyholm/psr7-server": "^1.0.2", "laminas/laminas-httphandlerrunner": "^2.1", "dragonmantank/cron-expression": "^3.3.2", - "halaxa/json-machine": "^1.1.1" + "halaxa/json-machine": "^1.1.1", + "psy/psysh": "^0.11.22" }, "suggest": { "ext-sockets": "For UDP commincations.", diff --git a/composer.lock b/composer.lock index 66a1019e..008b2478 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": "aeb69c4de3aed2bf54a9cced590bc95f", + "content-hash": "d221556bab57352f921d6bfaf9367fe3", "packages": [ { "name": "dragonmantank/cron-expression", @@ -376,6 +376,62 @@ ], "time": "2023-10-27T15:32:31+00:00" }, + { + "name": "nikic/php-parser", + "version": "v4.18.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "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": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" + }, + "time": "2023-12-10T21:03:43+00:00" + }, { "name": "nyholm/psr7", "version": "1.8.1", @@ -939,6 +995,86 @@ }, "time": "2021-10-29T13:26:27+00:00" }, + { + "name": "psy/psysh", + "version": "v0.11.22", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/psysh.git", + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/128fa1b608be651999ed9789c95e6e2a31b5802b", + "reference": "128fa1b608be651999ed9789c95e6e2a31b5802b", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-tokenizer": "*", + "nikic/php-parser": "^4.0 || ^3.1", + "php": "^8.0 || ^7.0.8", + "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4", + "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4" + }, + "conflict": { + "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.2" + }, + "suggest": { + "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)", + "ext-pdo-sqlite": "The doc command requires SQLite to work.", + "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.", + "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history." + }, + "bin": [ + "bin/psysh" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-0.11": "0.11.x-dev" + }, + "bamarni-bin": { + "bin-links": false, + "forward-command": false + } + }, + "autoload": { + "files": [ + "src/functions.php" + ], + "psr-4": { + "Psy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "An interactive shell for modern PHP.", + "homepage": "http://psysh.org", + "keywords": [ + "REPL", + "console", + "interactive", + "shell" + ], + "support": { + "issues": "https://github.com/bobthecow/psysh/issues", + "source": "https://github.com/bobthecow/psysh/tree/v0.11.22" + }, + "time": "2023-10-14T21:56:36+00:00" + }, { "name": "symfony/cache", "version": "v6.4.0", @@ -1825,6 +1961,91 @@ ], "time": "2023-11-29T08:40:23+00:00" }, + { + "name": "symfony/var-dumper", + "version": "v6.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^6.3|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/uid": "^5.4|^6.0|^7.0", + "twig/twig": "^2.13|^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "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 mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v6.4.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-11-09T08:28:32+00:00" + }, { "name": "symfony/var-exporter", "version": "v7.0.1", @@ -2160,62 +2381,6 @@ ], "time": "2023-03-08T13:26:56+00:00" }, - { - "name": "nikic/php-parser", - "version": "v4.18.0", - "source": { - "type": "git", - "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "reference": "1bcbb2179f97633e98bbbc87044ee2611c7d7999", - "shasum": "" - }, - "require": { - "ext-tokenizer": "*", - "php": ">=7.0" - }, - "require-dev": { - "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": "4.9-dev" - } - }, - "autoload": { - "psr-4": { - "PhpParser\\": "lib/PhpParser" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Nikita Popov" - } - ], - "description": "A PHP parser written in PHP", - "keywords": [ - "parser", - "php" - ], - "support": { - "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.18.0" - }, - "time": "2023-12-10T21:03:43+00:00" - }, { "name": "perftools/php-profiler", "version": "1.1.1", @@ -2817,12 +2982,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "ccb29669f00f1c5637c79c8e10efd10199696c65" + "reference": "3c2385497f806decca1e5abeba3cb8fd7caba4e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/ccb29669f00f1c5637c79c8e10efd10199696c65", - "reference": "ccb29669f00f1c5637c79c8e10efd10199696c65", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/3c2385497f806decca1e5abeba3cb8fd7caba4e0", + "reference": "3c2385497f806decca1e5abeba3cb8fd7caba4e0", "shasum": "" }, "conflict": { @@ -3394,7 +3559,7 @@ "twig/twig": "<1.44.7|>=2,<2.15.3|>=3,<3.4.3", "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", "typo3/cms-backend": ">=7,<=7.6.50|>=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", - "typo3/cms-core": "<=8.7.54|>=9,<=9.5.43|>=10,<=10.4.40|>=11,<=11.5.32|>=12,<=12.4.7", + "typo3/cms-core": "<8.7.55|>=9,<9.5.44|>=10,<10.4.41|>=11,<11.5.33|>=12,<12.4.8", "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.13|>=11,<=11.1", "typo3/cms-install": ">=12.2,<12.4.8", @@ -3526,7 +3691,7 @@ "type": "tidelift" } ], - "time": "2023-12-14T10:04:44+00:00" + "time": "2023-12-15T16:04:17+00:00" }, { "name": "sebastian/cli-parser", @@ -4492,91 +4657,6 @@ ], "time": "2020-09-28T06:39:44+00:00" }, - { - "name": "symfony/var-dumper", - "version": "v6.4.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/var-dumper.git", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "reference": "c40f7d17e91d8b407582ed51a2bbf83c52c367f6", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/polyfill-mbstring": "~1.0" - }, - "conflict": { - "symfony/console": "<5.4" - }, - "require-dev": { - "ext-iconv": "*", - "symfony/console": "^5.4|^6.0|^7.0", - "symfony/error-handler": "^6.3|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/uid": "^5.4|^6.0|^7.0", - "twig/twig": "^2.13|^3.0.4" - }, - "bin": [ - "Resources/bin/var-dump-server" - ], - "type": "library", - "autoload": { - "files": [ - "Resources/functions/dump.php" - ], - "psr-4": { - "Symfony\\Component\\VarDumper\\": "" - }, - "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 mechanisms for walking through any arbitrary PHP variable", - "homepage": "https://symfony.com", - "keywords": [ - "debug", - "dump" - ], - "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.4.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-11-09T08:28:32+00:00" - }, { "name": "theseer/tokenizer", "version": "1.2.2", @@ -4646,5 +4726,5 @@ "ext-simplexml": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/src/Commands/System/TinkerCommand.php b/src/Commands/System/TinkerCommand.php new file mode 100644 index 00000000..252a25e7 --- /dev/null +++ b/src/Commands/System/TinkerCommand.php @@ -0,0 +1,98 @@ +setName(self::ROUTE) + ->addOption('execute', 'e', InputOption::VALUE_OPTIONAL, 'Execute the given code using Tinker') + ->addArgument('include', InputArgument::IS_ARRAY, 'Include file(s) before starting tinker') + ->setDescription('A Interactive shell to manually write scripts.'); + } + + /** + * Run the interactive shell. + * + * @param iInput $input The input object containing the command input. + * @param iOutput $output The output object for writing command output. + * + * @return int Returns 0 on success or an error code on failure. + */ + protected function execute(iInput $input, iOutput $output): int + { + $this->getApplication()->setCatchExceptions(false); + + $config = Configuration::fromInput($input); + $config->setUpdateCheck(Checker::NEVER); + + if ($input->getOption('execute')) { + $config->setRawOutput(true); + } + + $shell = new Shell($config); + $shell->addCommands($this->getCommands()); + $shell->setIncludes($input->getArgument('include')); + + if ($code = $input->getOption('execute')) { + $shell->setOutput($output); + $shell->execute($code); + return 0; + } + + return $shell->run(); + } + + /** + * Get commands to pass through to PsySH. + * + * @return array The commands to pass through to PsySH. + */ + protected function getCommands(): array + { + $commands = []; + + foreach ($this->getApplication()->all() as $command) { + $commands[] = $command; + } + + return $commands; + } +}