diff --git a/www/boris/youtube.php b/www/boris/youtube.php index 93ac4a6..1680b5f 100644 --- a/www/boris/youtube.php +++ b/www/boris/youtube.php @@ -36,7 +36,7 @@ foreach ($videos as $v) { AstroCrowdBuster - + diff --git a/www/multitube/composer.json b/www/multitube/composer.json new file mode 100644 index 0000000..ead2e79 --- /dev/null +++ b/www/multitube/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "ipfs/php-client": "^1.4" + } +} diff --git a/www/multitube/composer.lock b/www/multitube/composer.lock new file mode 100644 index 0000000..0a7bbb9 --- /dev/null +++ b/www/multitube/composer.lock @@ -0,0 +1,1881 @@ +{ + "_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", + "This file is @generated automatically" + ], + "content-hash": "a7874ca1175d85cab3caf393af344215", + "packages": [ + { + "name": "clue/stream-filter", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "time": "2020-10-02T12:38:20+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/b17c5014ef81d212ac539f07a1001832df1b6d3b", + "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/cache": "1.*", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^0.12.20", + "phpunit/phpunit": "^7.5 || ^9.1.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2021-02-21T21:00:45+00:00" + }, + { + "name": "doctrine/lexer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "time": "2020-05-25T17:44:05+00:00" + }, + { + "name": "ipfs/php-client", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/digitalkaoz/php-ipfs-api.git", + "reference": "625fde907d2c631d81a60a5e6e3e617b9ba99400" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/digitalkaoz/php-ipfs-api/zipball/625fde907d2c631d81a60a5e6e3e617b9ba99400", + "reference": "625fde907d2c631d81a60a5e6e3e617b9ba99400", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.3", + "mattketmo/camel": "^1.1", + "nikic/php-parser": "^3.0", + "php": "^7.0", + "php-http/client-common": "^1.4", + "php-http/discovery": "^1.1", + "php-http/httplug": "^1.1", + "php-http/message": "^1.4", + "php-http/multipart-stream-builder": "^1.0", + "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/type-resolver": ">=0.1.7", + "pimple/pimple": "^3.0", + "rybakit/arguments-resolver": "^0.5.0", + "symfony/console": "^3.0", + "symfony/css-selector": "^3.0", + "symfony/dom-crawler": "^3.0", + "symfony/process": "^3.2", + "webmozart/assert": "^1.2" + }, + "require-dev": { + "php-http/guzzle6-adapter": ">=1.1.1", + "phpspec/phpspec": ">=3.0", + "symfony/var-dumper": "^3.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "IPFS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robert Schönthal", + "email": "robert.schoenthal@gmail.com" + } + ], + "description": "ipfs client library", + "keywords": [ + "api", + "ipfs" + ], + "time": "2018-12-24T22:55:43+00:00" + }, + { + "name": "mattketmo/camel", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/MattKetmo/camel.git", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MattKetmo/camel/zipball/2d7753c62787933f6761108acc76f95d8bfee191", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.6.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Camel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthieu Moquet", + "email": "matthieu@moquet.net" + } + ], + "description": "Tiny library to handle words case transformation", + "keywords": [ + "camelcase", + "case", + "lowercase", + "snakecase", + "transform" + ], + "time": "2015-05-13T13:51:08+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-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" + ], + "time": "2018-02-28T20:30:58+00:00" + }, + { + "name": "php-http/client-common", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "c0390ae3c8f2ae9d50901feef0127fb9e396f6b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/c0390ae3c8f2ae9d50901feef0127fb9e396f6b4", + "reference": "c0390ae3c8f2ae9d50901feef0127fb9e396f6b4", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "php-http/httplug": "^1.1", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.4", + "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2" + }, + "suggest": { + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ], + "time": "2019-11-18T08:54:36+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.13.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/788f72d64c43dc361e7fcc7464c3d947c64984a7", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "require-dev": { + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ], + "time": "2020-11-27T14:49:42+00:00" + }, + { + "name": "php-http/httplug", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "time": "2016-08-31T08:30:17+00:00" + }, + { + "name": "php-http/message", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/fb0dbce7355cad4f4f6a225f537c34d013571f29", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.1 || ^8.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "laminas/laminas-diactoros": "^2.0", + "phpspec/phpspec": "^5.1 || ^6.3", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "time": "2021-02-01T08:54:58+00:00" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "time": "2015-12-19T14:08:53+00:00" + }, + { + "name": "php-http/multipart-stream-builder", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/multipart-stream-builder.git", + "reference": "121299c2aad475a19087bc6298a1c9aa4d5c1ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/121299c2aad475a19087bc6298a1c9aa4d5c1ecc", + "reference": "121299c2aad475a19087bc6298a1c9aa4d5c1ecc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/discovery": "^1.7", + "php-http/message-factory": "^1.0.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "nyholm/psr7": "^1.0", + "php-http/message": "^1.5", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "A builder class that help you create a multipart stream", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "multipart stream", + "stream" + ], + "time": "2020-07-13T15:48:43+00:00" + }, + { + "name": "php-http/promise", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "time": "2020-07-07T09:29:14+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-10T14:09:06+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "pimple/pimple", + "version": "v3.4.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "86406047271859ffc13424a048541f4531f53601" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/86406047271859ffc13424a048541f4531f53601", + "reference": "86406047271859ffc13424a048541f4531f53601", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2021-03-06T08:28:00+00:00" + }, + { + "name": "psr/container", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.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" + ], + "time": "2021-03-05T17:36:06+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ], + "time": "2019-04-30T12:38:16+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "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": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2020-03-23T09:12:05+00:00" + }, + { + "name": "rybakit/arguments-resolver", + "version": "v0.5.1", + "source": { + "type": "git", + "url": "https://github.com/rybakit/arguments-resolver.git", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rybakit/arguments-resolver/zipball/5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "shasum": "" + }, + "require": { + "php": "^5.4|^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "ArgumentsResolver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eugene Leonovich", + "email": "gen.work@gmail.com" + } + ], + "description": "ArgumentsResolver allows you to determine the arguments to pass to a function or method.", + "homepage": "https://github.com/rybakit/arguments-resolver", + "keywords": [ + "arguments", + "callable", + "function", + "injection", + "invoke", + "method", + "parameters", + "reflection", + "resolver" + ], + "time": "2017-01-03T12:20:50+00:00" + }, + { + "name": "symfony/console", + "version": "v3.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.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": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2020-10-24T10:57:07+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v3.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/da3d9da2ce0026771f5fe64cb332158f1bd2bc33", + "reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2020-10-24T10:57:07+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/157bbec4fd773bae53c5483c50951a5530a2cc16", + "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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 tools to ease debugging PHP code", + "homepage": "https://symfony.com", + "time": "2021-01-28T16:54:48+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-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", + "time": "2020-09-07T11:33:47+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "ef97bcfbae5b384b4ca6c8d57b617722f15241a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ef97bcfbae5b384b4ca6c8d57b617722f15241a6", + "reference": "ef97bcfbae5b384b4ca6c8d57b617722f15241a6", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2020-10-24T10:57:07+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v5.2.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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 an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2021-01-27T12:56:27+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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" + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.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": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2021-01-22T09:19:47+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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" + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.22.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2021-01-07T16:49:33+00:00" + }, + { + "name": "symfony/process", + "version": "v3.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2020-10-24T10:57:07+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2021-03-09T10:59:23+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/www/multitube/vendor/autoload.php b/www/multitube/vendor/autoload.php new file mode 100644 index 0000000..badbcca --- /dev/null +++ b/www/multitube/vendor/autoload.php @@ -0,0 +1,7 @@ + $stream, callable $callback, int $read_write = STREAM_FILTER_ALL): resource` function can be used to +append a filter callback to the given stream. + +Each stream can have a list of filters attached. +This function appends a filter to the end of this list. + +If the given filter can not be added, it throws an `Exception`. + +The `$stream` can be any valid stream resource, such as: + +```php +$stream = fopen('demo.txt', 'w+'); +``` + +The `$callback` should be a valid callable function which accepts +an individual chunk of data and should return the updated chunk: + +```php +$filter = Filter\append($stream, function ($chunk) { + // will be called each time you read or write a $chunk to/from the stream + return $chunk; +}); +``` + +As such, you can also use native PHP functions or any other `callable`: + +```php +Filter\append($stream, 'strtoupper'); + +// will write "HELLO" to the underlying stream +fwrite($stream, 'hello'); +``` + +If the `$callback` accepts invocation without parameters, +then this signature will be invoked once ending (flushing) the filter: + +```php +Filter\append($stream, function ($chunk = null) { + if ($chunk === null) { + // will be called once ending the filter + return 'end'; + } + // will be called each time you read or write a $chunk to/from the stream + return $chunk; +}); + +fclose($stream); +``` + +> Note: Legacy PHP versions (PHP < 5.4) do not support passing additional data +from the end signal handler if the stream is being closed. + +If your callback throws an `Exception`, then the filter process will be aborted. +In order to play nice with PHP's stream handling, +the `Exception` will be transformed to a PHP warning instead: + +```php +Filter\append($stream, function ($chunk) { + throw new \RuntimeException('Unexpected chunk'); +}); + +// raises an E_USER_WARNING with "Error invoking filter: Unexpected chunk" +fwrite($stream, 'hello'); +``` + +The optional `$read_write` parameter can be used to only invoke the `$callback` +when either writing to the stream or only when reading from the stream: + +```php +Filter\append($stream, function ($chunk) { + // will be called each time you write to the stream + return $chunk; +}, STREAM_FILTER_WRITE); + +Filter\append($stream, function ($chunk) { + // will be called each time you read from the stream + return $chunk; +}, STREAM_FILTER_READ); +``` + +This function returns a filter resource which can be passed to [`remove()`](#remove). + +> Note that once a filter has been added to stream, the stream can no longer be passed to +> [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) +> (and family). +> +> > Warning: stream_select(): cannot cast a filtered stream on this system in {file} on line {line} +> +> This is due to limitations of PHP's stream filter support, as it can no longer reliably +> tell when the underlying stream resource is actually ready. +> As an alternative, consider calling `stream_select()` on the unfiltered stream and +> then pass the unfiltered data through the [`fun()`](#fun) function. + +### prepend() + +The `prepend(resource $stream, callable $callback, int $read_write = STREAM_FILTER_ALL): resource` function can be used to +prepend a filter callback to the given stream. + +Each stream can have a list of filters attached. +This function prepends a filter to the start of this list. + +If the given filter can not be added, it throws an `Exception`. + +```php +$filter = Filter\prepend($stream, function ($chunk) { + // will be called each time you read or write a $chunk to/from the stream + return $chunk; +}); +``` + +This function returns a filter resource which can be passed to [`remove()`](#remove). + +Except for the position in the list of filters, this function behaves exactly +like the [`append()`](#append) function. +For more details about its behavior, see also the [`append()`](#append) function. + +### fun() + +The `fun(string $filter, mixed $parameters = null): callable` function can be used to +create a filter function which uses the given built-in `$filter`. + +PHP comes with a useful set of [built-in filters](https://www.php.net/manual/en/filters.php). +Using `fun()` makes accessing these as easy as passing an input string to filter +and getting the filtered output string. + +```php +$fun = Filter\fun('string.rot13'); + +assert('grfg' === $fun('test')); +assert('test' === $fun($fun('test')); +``` + +Please note that not all filter functions may be available depending +on installed PHP extensions and the PHP version in use. +In particular, [HHVM](https://hhvm.com/) may not offer the same filter functions +or parameters as Zend PHP. +Accessing an unknown filter function will result in a `RuntimeException`: + +```php +Filter\fun('unknown'); // throws RuntimeException +``` + +Some filters may accept or require additional filter parameters – most +filters do not require filter parameters. +If given, the optional `$parameters` argument will be passed to the +underlying filter handler as-is. +In particular, note how *not passing* this parameter at all differs from +explicitly passing a `null` value (which many filters do not accept). +Please refer to the individual filter definition for more details. +For example, the `string.strip_tags` filter can be invoked like this: + +```php +$fun = Filter\fun('string.strip_tags', ''); + +$ret = $fun('h
i
'); +assert('hi' === $ret); +``` + +Under the hood, this function allocates a temporary memory stream, so it's +recommended to clean up the filter function after use. +Also, some filter functions (in particular the +[zlib compression filters](https://www.php.net/manual/en/filters.compression.php)) +may use internal buffers and may emit a final data chunk on close. +The filter function can be closed by invoking without any arguments: + +```php +$fun = Filter\fun('zlib.deflate'); + +$ret = $fun('hello') . $fun('world') . $fun(); +assert('helloworld' === gzinflate($ret)); +``` + +The filter function must not be used anymore after it has been closed. +Doing so will result in a `RuntimeException`: + +```php +$fun = Filter\fun('string.rot13'); +$fun(); + +$fun('test'); // throws RuntimeException +``` + +> Note: If you're using the zlib compression filters, then you should be wary +about engine inconsistencies between different PHP versions and HHVM. +These inconsistencies exist in the underlying PHP engines and there's little we +can do about this in this library. +[Our test suite](tests/) contains several test cases that exhibit these issues. +If you feel some test case is missing or outdated, we're happy to accept PRs! :) + +### remove() + +The `remove(resource $filter): bool` function can be used to +remove a filter previously added via [`append()`](#append) or [`prepend()`](#prepend). + +```php +$filter = Filter\append($stream, function () { + // … +}); +Filter\remove($filter); +``` + +## Install + +The recommended way to install this library is [through Composer](https://getcomposer.org). +[New to Composer?](https://getcomposer.org/doc/00-intro.md) + +This project follows [SemVer](https://semver.org/). +This will install the latest supported version: + +```bash +$ composer require clue/stream-filter:^1.5 +``` + +See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades. + +This project aims to run on any platform and thus does not require any PHP +extensions and supports running on legacy PHP 5.3 through current PHP 7+ and +HHVM. +It's *highly recommended to use PHP 7+* for this project. +Older PHP versions may suffer from a number of inconsistencies documented above. + +## Tests + +To run the test suite, you first need to clone this repo and then install all +dependencies [through Composer](https://getcomposer.org): + +```bash +$ composer install +``` + +To run the test suite, go to the project root and run: + +```bash +$ php vendor/bin/phpunit +``` + +## License + +This project is released under the permissive [MIT license](LICENSE). + +> Did you know that I offer custom development services and issuing invoices for + sponsorships of releases and for contributions? Contact me (@clue) for details. diff --git a/www/multitube/vendor/clue/stream-filter/composer.json b/www/multitube/vendor/clue/stream-filter/composer.json new file mode 100644 index 0000000..797fb53 --- /dev/null +++ b/www/multitube/vendor/clue/stream-filter/composer.json @@ -0,0 +1,26 @@ +{ + "name": "clue/stream-filter", + "description": "A simple and modern approach to stream filtering in PHP", + "keywords": ["stream", "callback", "filter", "php_user_filter", "stream_filter_append", "stream_filter_register", "bucket brigade"], + "homepage": "https://github.com/clue/php-stream-filter", + "license": "MIT", + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" + }, + "autoload": { + "psr-4": { "Clue\\StreamFilter\\": "src/" }, + "files": [ "src/functions_include.php" ] + }, + "autoload-dev": { + "psr-4": { "Clue\\Tests\\StreamFilter\\": "tests/" } + } +} diff --git a/www/multitube/vendor/clue/stream-filter/src/CallbackFilter.php b/www/multitube/vendor/clue/stream-filter/src/CallbackFilter.php new file mode 100644 index 0000000..1ca074b --- /dev/null +++ b/www/multitube/vendor/clue/stream-filter/src/CallbackFilter.php @@ -0,0 +1,114 @@ +closed = false; + + if (!\is_callable($this->params)) { + throw new \InvalidArgumentException('No valid callback parameter given to stream_filter_(append|prepend)'); + } + $this->callback = $this->params; + + // callback supports end event if it accepts invocation without arguments + $ref = new \ReflectionFunction($this->callback); + $this->supportsClose = ($ref->getNumberOfRequiredParameters() === 0); + + return true; + } + + public function onClose() + { + $this->closed = true; + + // callback supports closing and is not already closed + if ($this->supportsClose) { + $this->supportsClose = false; + // invoke without argument to signal end and discard resulting buffer + try { + \call_user_func($this->callback); + } catch (\Exception $ignored) { + // this might be called during engine shutdown, so it's not safe + // to raise any errors or exceptions here + // trigger_error('Error closing filter: ' . $ignored->getMessage(), E_USER_WARNING); + } + } + + $this->callback = null; + } + + public function filter($in, $out, &$consumed, $closing) + { + // concatenate whole buffer from input brigade + $data = ''; + while ($bucket = \stream_bucket_make_writeable($in)) { + $consumed += $bucket->datalen; + $data .= $bucket->data; + } + + // skip processing callback that already ended + if ($this->closed) { + return \PSFS_FEED_ME; + } + + // only invoke filter function if buffer is not empty + // this may skip flushing a closing filter + if ($data !== '') { + try { + $data = \call_user_func($this->callback, $data); + } catch (\Exception $e) { + // exception should mark filter as closed + $this->onClose(); + \trigger_error('Error invoking filter: ' . $e->getMessage(), \E_USER_WARNING); + + return \PSFS_ERR_FATAL; + } + } + + // mark filter as closed after processing closing chunk + if ($closing) { + $this->closed = true; + + // callback supports closing and is not already closed + if ($this->supportsClose) { + $this->supportsClose = false; + + // invoke without argument to signal end and append resulting buffer + try { + $data .= \call_user_func($this->callback); + } catch (\Exception $e) { + \trigger_error('Error ending filter: ' . $e->getMessage(), \E_USER_WARNING); + + return \PSFS_ERR_FATAL; + } + } + } + + if ($data !== '') { + // create a new bucket for writing the resulting buffer to the output brigade + // reusing an existing bucket turned out to be bugged in some environments (ancient PHP versions and HHVM) + $bucket = @\stream_bucket_new($this->stream, $data); + + // legacy PHP versions (PHP < 5.4) do not support passing data from the event signal handler + // because closing the stream invalidates the stream and its stream bucket brigade before + // invoking the filter close handler. + if ($bucket !== false) { + \stream_bucket_append($out, $bucket); + } + } + + return \PSFS_PASS_ON; + } +} diff --git a/www/multitube/vendor/clue/stream-filter/src/functions.php b/www/multitube/vendor/clue/stream-filter/src/functions.php new file mode 100644 index 0000000..4746d88 --- /dev/null +++ b/www/multitube/vendor/clue/stream-filter/src/functions.php @@ -0,0 +1,327 @@ + Note: Legacy PHP versions (PHP < 5.4) do not support passing additional data + * from the end signal handler if the stream is being closed. + * + * If your callback throws an `Exception`, then the filter process will be aborted. + * In order to play nice with PHP's stream handling, + * the `Exception` will be transformed to a PHP warning instead: + * + * ```php + * Filter\append($stream, function ($chunk) { + * throw new \RuntimeException('Unexpected chunk'); + * }); + * + * // raises an E_USER_WARNING with "Error invoking filter: Unexpected chunk" + * fwrite($stream, 'hello'); + * ``` + * + * The optional `$read_write` parameter can be used to only invoke the `$callback` + * when either writing to the stream or only when reading from the stream: + * + * ```php + * Filter\append($stream, function ($chunk) { + * // will be called each time you write to the stream + * return $chunk; + * }, STREAM_FILTER_WRITE); + * + * Filter\append($stream, function ($chunk) { + * // will be called each time you read from the stream + * return $chunk; + * }, STREAM_FILTER_READ); + * ``` + * + * This function returns a filter resource which can be passed to [`remove()`](#remove). + * + * > Note that once a filter has been added to stream, the stream can no longer be passed to + * > [`stream_select()`](https://www.php.net/manual/en/function.stream-select.php) + * > (and family). + * > + * > > Warning: stream_select(): cannot cast a filtered stream on this system in {file} on line {line} + * > + * > This is due to limitations of PHP's stream filter support, as it can no longer reliably + * > tell when the underlying stream resource is actually ready. + * > As an alternative, consider calling `stream_select()` on the unfiltered stream and + * > then pass the unfiltered data through the [`fun()`](#fun) function. + * + * @param resource $stream + * @param callable $callback + * @param int $read_write + * @return resource filter resource which can be used for `remove()` + * @throws \Exception on error + * @uses stream_filter_append() + */ +function append($stream, $callback, $read_write = STREAM_FILTER_ALL) +{ + $ret = @\stream_filter_append($stream, register(), $read_write, $callback); + + // PHP 8 throws above on type errors, older PHP and memory issues can throw here + // @codeCoverageIgnoreStart + if ($ret === false) { + $error = \error_get_last() + array('message' => ''); + throw new \RuntimeException('Unable to append filter: ' . $error['message']); + } + // @codeCoverageIgnoreEnd + + return $ret; +} + +/** + * Prepend a filter callback to the given stream. + * + * Each stream can have a list of filters attached. + * This function prepends a filter to the start of this list. + * + * If the given filter can not be added, it throws an `Exception`. + * + * ```php + * $filter = Filter\prepend($stream, function ($chunk) { + * // will be called each time you read or write a $chunk to/from the stream + * return $chunk; + * }); + * ``` + * + * This function returns a filter resource which can be passed to [`remove()`](#remove). + * + * Except for the position in the list of filters, this function behaves exactly + * like the [`append()`](#append) function. + * For more details about its behavior, see also the [`append()`](#append) function. + * + * @param resource $stream + * @param callable $callback + * @param int $read_write + * @return resource filter resource which can be used for `remove()` + * @throws \Exception on error + * @uses stream_filter_prepend() + */ +function prepend($stream, $callback, $read_write = STREAM_FILTER_ALL) +{ + $ret = @\stream_filter_prepend($stream, register(), $read_write, $callback); + + // PHP 8 throws above on type errors, older PHP and memory issues can throw here + // @codeCoverageIgnoreStart + if ($ret === false) { + $error = \error_get_last() + array('message' => ''); + throw new \RuntimeException('Unable to prepend filter: ' . $error['message']); + } + // @codeCoverageIgnoreEnd + + return $ret; +} + +/** + * Create a filter function which uses the given built-in `$filter`. + * + * PHP comes with a useful set of [built-in filters](https://www.php.net/manual/en/filters.php). + * Using `fun()` makes accessing these as easy as passing an input string to filter + * and getting the filtered output string. + * + * ```php + * $fun = Filter\fun('string.rot13'); + * + * assert('grfg' === $fun('test')); + * assert('test' === $fun($fun('test')); + * ``` + * + * Please note that not all filter functions may be available depending + * on installed PHP extensions and the PHP version in use. + * In particular, [HHVM](https://hhvm.com/) may not offer the same filter functions + * or parameters as Zend PHP. + * Accessing an unknown filter function will result in a `RuntimeException`: + * + * ```php + * Filter\fun('unknown'); // throws RuntimeException + * ``` + * + * Some filters may accept or require additional filter parameters – most + * filters do not require filter parameters. + * If given, the optional `$parameters` argument will be passed to the + * underlying filter handler as-is. + * In particular, note how *not passing* this parameter at all differs from + * explicitly passing a `null` value (which many filters do not accept). + * Please refer to the individual filter definition for more details. + * For example, the `string.strip_tags` filter can be invoked like this: + * + * ```php + * $fun = Filter\fun('string.strip_tags', '
'); + * + * $ret = $fun('h
i
'); + * assert('hi' === $ret); + * ``` + * + * Under the hood, this function allocates a temporary memory stream, so it's + * recommended to clean up the filter function after use. + * Also, some filter functions (in particular the + * [zlib compression filters](https://www.php.net/manual/en/filters.compression.php)) + * may use internal buffers and may emit a final data chunk on close. + * The filter function can be closed by invoking without any arguments: + * + * ```php + * $fun = Filter\fun('zlib.deflate'); + * + * $ret = $fun('hello') . $fun('world') . $fun(); + * assert('helloworld' === gzinflate($ret)); + * ``` + * + * The filter function must not be used anymore after it has been closed. + * Doing so will result in a `RuntimeException`: + * + * ```php + * $fun = Filter\fun('string.rot13'); + * $fun(); + * + * $fun('test'); // throws RuntimeException + * ``` + * + * > Note: If you're using the zlib compression filters, then you should be wary + * about engine inconsistencies between different PHP versions and HHVM. + * These inconsistencies exist in the underlying PHP engines and there's little we + * can do about this in this library. + * [Our test suite](tests/) contains several test cases that exhibit these issues. + * If you feel some test case is missing or outdated, we're happy to accept PRs! :) + * + * @param string $filter built-in filter name. See stream_get_filters() or http://php.net/manual/en/filters.php + * @param mixed $parameters (optional) parameters to pass to the built-in filter as-is + * @return callable a filter callback which can be append()'ed or prepend()'ed + * @throws \RuntimeException on error + * @link http://php.net/manual/en/filters.php + * @see stream_get_filters() + * @see append() + */ +function fun($filter, $parameters = null) +{ + $fp = \fopen('php://memory', 'w'); + if (\func_num_args() === 1) { + $filter = @\stream_filter_append($fp, $filter, \STREAM_FILTER_WRITE); + } else { + $filter = @\stream_filter_append($fp, $filter, \STREAM_FILTER_WRITE, $parameters); + } + + if ($filter === false) { + \fclose($fp); + $error = \error_get_last() + array('message' => ''); + throw new \RuntimeException('Unable to access built-in filter: ' . $error['message']); + } + + // append filter function which buffers internally + $buffer = ''; + append($fp, function ($chunk) use (&$buffer) { + $buffer .= $chunk; + + // always return empty string in order to skip actually writing to stream resource + return ''; + }, \STREAM_FILTER_WRITE); + + $closed = false; + + return function ($chunk = null) use ($fp, $filter, &$buffer, &$closed) { + if ($closed) { + throw new \RuntimeException('Unable to perform operation on closed stream'); + } + if ($chunk === null) { + $closed = true; + $buffer = ''; + \fclose($fp); + return $buffer; + } + // initialize buffer and invoke filters by attempting to write to stream + $buffer = ''; + \fwrite($fp, $chunk); + + // buffer now contains everything the filter function returned + return $buffer; + }; +} + +/** + * Remove a filter previously added via `append()` or `prepend()`. + * + * ```php + * $filter = Filter\append($stream, function () { + * // … + * }); + * Filter\remove($filter); + * ``` + * + * @param resource $filter + * @return bool true on success or false on error + * @throws \RuntimeException on error + * @uses stream_filter_remove() + */ +function remove($filter) +{ + if (@\stream_filter_remove($filter) === false) { + // PHP 8 throws above on type errors, older PHP and memory issues can throw here + $error = \error_get_last(); + throw new \RuntimeException('Unable to remove filter: ' . $error['message']); + } +} + +/** + * Registers the callback filter and returns the resulting filter name + * + * There should be little reason to call this function manually. + * + * @return string filter name + * @uses CallbackFilter + */ +function register() +{ + static $registered = null; + if ($registered === null) { + $registered = 'stream-callback'; + \stream_filter_register($registered, __NAMESPACE__ . '\CallbackFilter'); + } + return $registered; +} diff --git a/www/multitube/vendor/clue/stream-filter/src/functions_include.php b/www/multitube/vendor/clue/stream-filter/src/functions_include.php new file mode 100644 index 0000000..4b315ae --- /dev/null +++ b/www/multitube/vendor/clue/stream-filter/src/functions_include.php @@ -0,0 +1,6 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + private $classMapAuthoritative = false; + private $missingClasses = array(); + private $apcuPrefix; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * APCu prefix to use to cache found/not-found classes, if the extension is enabled. + * + * @param string|null $apcuPrefix + */ + public function setApcuPrefix($apcuPrefix) + { + $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + } + + /** + * The APCu prefix in use, or null if APCu caching is not enabled. + * + * @return string|null + */ + public function getApcuPrefix() + { + return $this->apcuPrefix; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) { + return false; + } + if (null !== $this->apcuPrefix) { + $file = apcu_fetch($this->apcuPrefix.$class, $hit); + if ($hit) { + return $file; + } + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if (false === $file && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if (null !== $this->apcuPrefix) { + apcu_add($this->apcuPrefix.$class, $file); + } + + if (false === $file) { + // Remember that this class does not exist. + $this->missingClasses[$class] = true; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath.'\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + + return false; + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/www/multitube/vendor/composer/LICENSE b/www/multitube/vendor/composer/LICENSE new file mode 100644 index 0000000..f0157a6 --- /dev/null +++ b/www/multitube/vendor/composer/LICENSE @@ -0,0 +1,56 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Composer +Upstream-Contact: Jordi Boggiano +Source: https://github.com/composer/composer + +Files: * +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano +License: Expat + +Files: src/Composer/Util/TlsHelper.php +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano + 2013, Evan Coury +License: Expat and BSD-2-Clause + +License: BSD-2-Clause + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + . + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. diff --git a/www/multitube/vendor/composer/autoload_classmap.php b/www/multitube/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..e883840 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_classmap.php @@ -0,0 +1,14 @@ + $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', +); diff --git a/www/multitube/vendor/composer/autoload_files.php b/www/multitube/vendor/composer/autoload_files.php new file mode 100644 index 0000000..04708a8 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_files.php @@ -0,0 +1,16 @@ + $vendorDir . '/clue/stream-filter/src/functions_include.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php', + '8cff32064859f4559445b89279f3199c' => $vendorDir . '/php-http/message/src/filters.php', + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', +); diff --git a/www/multitube/vendor/composer/autoload_namespaces.php b/www/multitube/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..f3ed337 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_namespaces.php @@ -0,0 +1,11 @@ + array($vendorDir . '/pimple/pimple/src'), + 'Camel' => array($vendorDir . '/mattketmo/camel/src'), +); diff --git a/www/multitube/vendor/composer/autoload_psr4.php b/www/multitube/vendor/composer/autoload_psr4.php new file mode 100644 index 0000000..139b644 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_psr4.php @@ -0,0 +1,36 @@ + array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'), + 'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'), + 'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'), + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), + 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), + 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), + 'Symfony\\Component\\OptionsResolver\\' => array($vendorDir . '/symfony/options-resolver'), + 'Symfony\\Component\\DomCrawler\\' => array($vendorDir . '/symfony/dom-crawler'), + 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'), + 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'), + 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'), + 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), + 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), + 'Psr\\Container\\' => array($vendorDir . '/psr/container/src'), + 'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'), + 'IPFS\\' => array($vendorDir . '/ipfs/php-client/src'), + 'Http\\Promise\\' => array($vendorDir . '/php-http/promise/src'), + 'Http\\Message\\MultipartStream\\' => array($vendorDir . '/php-http/multipart-stream-builder/src'), + 'Http\\Message\\' => array($vendorDir . '/php-http/message/src', $vendorDir . '/php-http/message-factory/src'), + 'Http\\Discovery\\' => array($vendorDir . '/php-http/discovery/src'), + 'Http\\Client\\Common\\' => array($vendorDir . '/php-http/client-common/src'), + 'Http\\Client\\' => array($vendorDir . '/php-http/httplug/src'), + 'Doctrine\\Common\\Lexer\\' => array($vendorDir . '/doctrine/lexer/lib/Doctrine/Common/Lexer'), + 'Doctrine\\Common\\Annotations\\' => array($vendorDir . '/doctrine/annotations/lib/Doctrine/Common/Annotations'), + 'Clue\\StreamFilter\\' => array($vendorDir . '/clue/stream-filter/src'), + 'ArgumentsResolver\\' => array($vendorDir . '/rybakit/arguments-resolver/src'), +); diff --git a/www/multitube/vendor/composer/autoload_real.php b/www/multitube/vendor/composer/autoload_real.php new file mode 100644 index 0000000..987f045 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_real.php @@ -0,0 +1,70 @@ += 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequirebf8c14254ed88976607b4d25d8ae4b79($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequirebf8c14254ed88976607b4d25d8ae4b79($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/www/multitube/vendor/composer/autoload_static.php b/www/multitube/vendor/composer/autoload_static.php new file mode 100644 index 0000000..bfaf520 --- /dev/null +++ b/www/multitube/vendor/composer/autoload_static.php @@ -0,0 +1,226 @@ + __DIR__ . '/..' . '/clue/stream-filter/src/functions_include.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + 'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php', + '8cff32064859f4559445b89279f3199c' => __DIR__ . '/..' . '/php-http/message/src/filters.php', + '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', + ); + + public static $prefixLengthsPsr4 = array ( + 'p' => + array ( + 'phpDocumentor\\Reflection\\' => 25, + ), + 'W' => + array ( + 'Webmozart\\Assert\\' => 17, + ), + 'S' => + array ( + 'Symfony\\Polyfill\\Php80\\' => 23, + 'Symfony\\Polyfill\\Php73\\' => 23, + 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Polyfill\\Ctype\\' => 23, + 'Symfony\\Component\\Process\\' => 26, + 'Symfony\\Component\\OptionsResolver\\' => 34, + 'Symfony\\Component\\DomCrawler\\' => 29, + 'Symfony\\Component\\Debug\\' => 24, + 'Symfony\\Component\\CssSelector\\' => 30, + 'Symfony\\Component\\Console\\' => 26, + ), + 'P' => + array ( + 'Psr\\Log\\' => 8, + 'Psr\\Http\\Message\\' => 17, + 'Psr\\Container\\' => 14, + 'PhpParser\\' => 10, + ), + 'I' => + array ( + 'IPFS\\' => 5, + ), + 'H' => + array ( + 'Http\\Promise\\' => 13, + 'Http\\Message\\MultipartStream\\' => 29, + 'Http\\Message\\' => 13, + 'Http\\Discovery\\' => 15, + 'Http\\Client\\Common\\' => 19, + 'Http\\Client\\' => 12, + ), + 'D' => + array ( + 'Doctrine\\Common\\Lexer\\' => 22, + 'Doctrine\\Common\\Annotations\\' => 28, + ), + 'C' => + array ( + 'Clue\\StreamFilter\\' => 18, + ), + 'A' => + array ( + 'ArgumentsResolver\\' => 18, + ), + ); + + public static $prefixDirsPsr4 = array ( + 'phpDocumentor\\Reflection\\' => + array ( + 0 => __DIR__ . '/..' . '/phpdocumentor/reflection-common/src', + 1 => __DIR__ . '/..' . '/phpdocumentor/reflection-docblock/src', + 2 => __DIR__ . '/..' . '/phpdocumentor/type-resolver/src', + ), + 'Webmozart\\Assert\\' => + array ( + 0 => __DIR__ . '/..' . '/webmozart/assert/src', + ), + 'Symfony\\Polyfill\\Php80\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php80', + ), + 'Symfony\\Polyfill\\Php73\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), + 'Symfony\\Polyfill\\Mbstring\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', + ), + 'Symfony\\Polyfill\\Ctype\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', + ), + 'Symfony\\Component\\Process\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/process', + ), + 'Symfony\\Component\\OptionsResolver\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/options-resolver', + ), + 'Symfony\\Component\\DomCrawler\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/dom-crawler', + ), + 'Symfony\\Component\\Debug\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/debug', + ), + 'Symfony\\Component\\CssSelector\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/css-selector', + ), + 'Symfony\\Component\\Console\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/console', + ), + 'Psr\\Log\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/log/Psr/Log', + ), + 'Psr\\Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/http-factory/src', + 1 => __DIR__ . '/..' . '/psr/http-message/src', + ), + 'Psr\\Container\\' => + array ( + 0 => __DIR__ . '/..' . '/psr/container/src', + ), + 'PhpParser\\' => + array ( + 0 => __DIR__ . '/..' . '/nikic/php-parser/lib/PhpParser', + ), + 'IPFS\\' => + array ( + 0 => __DIR__ . '/..' . '/ipfs/php-client/src', + ), + 'Http\\Promise\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/promise/src', + ), + 'Http\\Message\\MultipartStream\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/multipart-stream-builder/src', + ), + 'Http\\Message\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/message/src', + 1 => __DIR__ . '/..' . '/php-http/message-factory/src', + ), + 'Http\\Discovery\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/discovery/src', + ), + 'Http\\Client\\Common\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/client-common/src', + ), + 'Http\\Client\\' => + array ( + 0 => __DIR__ . '/..' . '/php-http/httplug/src', + ), + 'Doctrine\\Common\\Lexer\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/lexer/lib/Doctrine/Common/Lexer', + ), + 'Doctrine\\Common\\Annotations\\' => + array ( + 0 => __DIR__ . '/..' . '/doctrine/annotations/lib/Doctrine/Common/Annotations', + ), + 'Clue\\StreamFilter\\' => + array ( + 0 => __DIR__ . '/..' . '/clue/stream-filter/src', + ), + 'ArgumentsResolver\\' => + array ( + 0 => __DIR__ . '/..' . '/rybakit/arguments-resolver/src', + ), + ); + + public static $prefixesPsr0 = array ( + 'P' => + array ( + 'Pimple' => + array ( + 0 => __DIR__ . '/..' . '/pimple/pimple/src', + ), + ), + 'C' => + array ( + 'Camel' => + array ( + 0 => __DIR__ . '/..' . '/mattketmo/camel/src', + ), + ), + ); + + public static $classMap = array ( + 'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php', + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', + 'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php', + 'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php', + 'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + $loader->prefixLengthsPsr4 = ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::$prefixLengthsPsr4; + $loader->prefixDirsPsr4 = ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::$prefixDirsPsr4; + $loader->prefixesPsr0 = ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::$prefixesPsr0; + $loader->classMap = ComposerStaticInitbf8c14254ed88976607b4d25d8ae4b79::$classMap; + + }, null, ClassLoader::class); + } +} diff --git a/www/multitube/vendor/composer/installed.json b/www/multitube/vendor/composer/installed.json new file mode 100644 index 0000000..40a2094 --- /dev/null +++ b/www/multitube/vendor/composer/installed.json @@ -0,0 +1,1933 @@ +[ + { + "name": "clue/stream-filter", + "version": "v1.5.0", + "version_normalized": "1.5.0.0", + "source": { + "type": "git", + "url": "https://github.com/clue/stream-filter.git", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/stream-filter/zipball/aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "reference": "aeb7d8ea49c7963d3b581378955dbf5bc49aa320", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36" + }, + "time": "2020-10-02T12:38:20+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@clue.engineering" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ] + }, + { + "name": "doctrine/annotations", + "version": "1.12.1", + "version_normalized": "1.12.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/b17c5014ef81d212ac539f07a1001832df1b6d3b", + "reference": "b17c5014ef81d212ac539f07a1001832df1b6d3b", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/cache": "1.*", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^0.12.20", + "phpunit/phpunit": "^7.5 || ^9.1.5" + }, + "time": "2021-02-21T21:00:45+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ] + }, + { + "name": "doctrine/lexer", + "version": "1.2.1", + "version_normalized": "1.2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/e864bbf5904cb8f5bb334f99209b48018522f042", + "reference": "e864bbf5904cb8f5bb334f99209b48018522f042", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "time": "2020-05-25T17:44:05+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ] + }, + { + "name": "ipfs/php-client", + "version": "1.4.1", + "version_normalized": "1.4.1.0", + "source": { + "type": "git", + "url": "https://github.com/digitalkaoz/php-ipfs-api.git", + "reference": "625fde907d2c631d81a60a5e6e3e617b9ba99400" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/digitalkaoz/php-ipfs-api/zipball/625fde907d2c631d81a60a5e6e3e617b9ba99400", + "reference": "625fde907d2c631d81a60a5e6e3e617b9ba99400", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.3", + "mattketmo/camel": "^1.1", + "nikic/php-parser": "^3.0", + "php": "^7.0", + "php-http/client-common": "^1.4", + "php-http/discovery": "^1.1", + "php-http/httplug": "^1.1", + "php-http/message": "^1.4", + "php-http/multipart-stream-builder": "^1.0", + "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/type-resolver": ">=0.1.7", + "pimple/pimple": "^3.0", + "rybakit/arguments-resolver": "^0.5.0", + "symfony/console": "^3.0", + "symfony/css-selector": "^3.0", + "symfony/dom-crawler": "^3.0", + "symfony/process": "^3.2", + "webmozart/assert": "^1.2" + }, + "require-dev": { + "php-http/guzzle6-adapter": ">=1.1.1", + "phpspec/phpspec": ">=3.0", + "symfony/var-dumper": "^3.0" + }, + "time": "2018-12-24T22:55:43+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "IPFS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Robert Schönthal", + "email": "robert.schoenthal@gmail.com" + } + ], + "description": "ipfs client library", + "keywords": [ + "api", + "ipfs" + ] + }, + { + "name": "mattketmo/camel", + "version": "v1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/MattKetmo/camel.git", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MattKetmo/camel/zipball/2d7753c62787933f6761108acc76f95d8bfee191", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.6.*" + }, + "time": "2015-05-13T13:51:08+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Camel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthieu Moquet", + "email": "matthieu@moquet.net" + } + ], + "description": "Tiny library to handle words case transformation", + "keywords": [ + "camelcase", + "case", + "lowercase", + "snakecase", + "transform" + ] + }, + { + "name": "nikic/php-parser", + "version": "v3.1.5", + "version_normalized": "3.1.5.0", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "time": "2018-02-28T20:30:58+00:00", + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "installation-source": "dist", + "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" + ] + }, + { + "name": "php-http/client-common", + "version": "1.10.0", + "version_normalized": "1.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "c0390ae3c8f2ae9d50901feef0127fb9e396f6b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/c0390ae3c8f2ae9d50901feef0127fb9e396f6b4", + "reference": "c0390ae3c8f2ae9d50901feef0127fb9e396f6b4", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "php-http/httplug": "^1.1", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.4", + "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2" + }, + "suggest": { + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "time": "2019-11-18T08:54:36+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ] + }, + { + "name": "php-http/discovery", + "version": "1.13.0", + "version_normalized": "1.13.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/788f72d64c43dc361e7fcc7464c3d947c64984a7", + "reference": "788f72d64c43dc361e7fcc7464c3d947c64984a7", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "require-dev": { + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + }, + "time": "2020-11-27T14:49:42+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ] + }, + { + "name": "php-http/httplug", + "version": "v1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "time": "2016-08-31T08:30:17+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ] + }, + { + "name": "php-http/message", + "version": "1.11.0", + "version_normalized": "1.11.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/fb0dbce7355cad4f4f6a225f537c34d013571f29", + "reference": "fb0dbce7355cad4f4f6a225f537c34d013571f29", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.5", + "php": "^7.1 || ^8.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.6", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "laminas/laminas-diactoros": "^2.0", + "phpspec/phpspec": "^5.1 || ^6.3", + "slim/slim": "^3.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "time": "2021-02-01T08:54:58+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ] + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "time": "2015-12-19T14:08:53+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ] + }, + { + "name": "php-http/multipart-stream-builder", + "version": "1.1.2", + "version_normalized": "1.1.2.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/multipart-stream-builder.git", + "reference": "121299c2aad475a19087bc6298a1c9aa4d5c1ecc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/121299c2aad475a19087bc6298a1c9aa4d5c1ecc", + "reference": "121299c2aad475a19087bc6298a1c9aa4d5c1ecc", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "php-http/discovery": "^1.7", + "php-http/message-factory": "^1.0.2", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "nyholm/psr7": "^1.0", + "php-http/message": "^1.5", + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3" + }, + "time": "2020-07-13T15:48:43+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "A builder class that help you create a multipart stream", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "multipart stream", + "stream" + ] + }, + { + "name": "php-http/promise", + "version": "1.1.0", + "version_normalized": "1.1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "reference": "4c4c1f9b7289a2ec57cde7f1e9762a5789506f88", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage": "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" + }, + "time": "2020-07-07T09:29:14+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ] + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "time": "2017-09-11T18:02:19+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "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" + ] + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.3.2", + "version_normalized": "3.3.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "time": "2017-11-10T14:09:06+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock." + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "version_normalized": "0.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "time": "2017-07-14T14:27:02+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ] + }, + { + "name": "pimple/pimple", + "version": "v3.4.0", + "version_normalized": "3.4.0.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "86406047271859ffc13424a048541f4531f53601" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/86406047271859ffc13424a048541f4531f53601", + "reference": "86406047271859ffc13424a048541f4531f53601", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "time": "2021-03-06T08:28:00+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "https://pimple.symfony.com", + "keywords": [ + "container", + "dependency injection" + ] + }, + { + "name": "psr/container", + "version": "1.1.1", + "version_normalized": "1.1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf", + "reference": "8622567409010282b7aeebe4bb841fe98b58dcaf", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "time": "2021-03-05T17:36:06+00:00", + "type": "library", + "installation-source": "dist", + "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" + ] + }, + { + "name": "psr/http-factory", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be", + "shasum": "" + }, + "require": { + "php": ">=7.0.0", + "psr/http-message": "^1.0" + }, + "time": "2019-04-30T12:38:16+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", + "psr", + "psr-17", + "psr-7", + "request", + "response" + ] + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2016-08-06T14:39:51+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ] + }, + { + "name": "psr/log", + "version": "1.1.3", + "version_normalized": "1.1.3.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", + "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "time": "2020-03-23T09:12:05+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ] + }, + { + "name": "rybakit/arguments-resolver", + "version": "v0.5.1", + "version_normalized": "0.5.1.0", + "source": { + "type": "git", + "url": "https://github.com/rybakit/arguments-resolver.git", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rybakit/arguments-resolver/zipball/5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "shasum": "" + }, + "require": { + "php": "^5.4|^7.0" + }, + "time": "2017-01-03T12:20:50+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "ArgumentsResolver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eugene Leonovich", + "email": "gen.work@gmail.com" + } + ], + "description": "ArgumentsResolver allows you to determine the arguments to pass to a function or method.", + "homepage": "https://github.com/rybakit/arguments-resolver", + "keywords": [ + "arguments", + "callable", + "function", + "injection", + "invoke", + "method", + "parameters", + "reflection", + "resolver" + ] + }, + { + "name": "symfony/console", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "reference": "a10b1da6fc93080c180bba7219b5ff5b7518fe81", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "provide": { + "psr/log-implementation": "1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "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": "Symfony Console Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/css-selector", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/da3d9da2ce0026771f5fe64cb332158f1bd2bc33", + "reference": "da3d9da2ce0026771f5fe64cb332158f1bd2bc33", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/debug", + "version": "v4.4.20", + "version_normalized": "4.4.20.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/157bbec4fd773bae53c5483c50951a5530a2cc16", + "reference": "157bbec4fd773bae53c5483c50951a5530a2cc16", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "psr/log": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "time": "2021-01-28T16:54:48+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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 tools to ease debugging PHP code", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.2.0", + "version_normalized": "2.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "reference": "5fa56b4074d1ae755beb55617ddafe6f5d78f665", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2020-09-07T11:33:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "installation-source": "dist", + "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" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "ef97bcfbae5b384b4ca6c8d57b617722f15241a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ef97bcfbae5b384b4ca6c8d57b617722f15241a6", + "reference": "ef97bcfbae5b384b4ca6c8d57b617722f15241a6", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Symfony DomCrawler Component", + "homepage": "https://symfony.com" + }, + { + "name": "symfony/options-resolver", + "version": "v5.2.4", + "version_normalized": "5.2.4.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "reference": "5d0f633f9bbfcf7ec642a2b5037268e61b0a62ce", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", + "symfony/polyfill-php73": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "time": "2021-01-27T12:56:27+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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 an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ] + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.22.1", + "version_normalized": "1.22.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", + "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "time": "2021-01-07T16:49:33+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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" + ] + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.22.1", + "version_normalized": "1.22.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/5232de97ee3b75b0360528dae24e73db49566ab1", + "reference": "5232de97ee3b75b0360528dae24e73db49566ab1", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "time": "2021-01-22T09:19:47+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.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": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.22.1", + "version_normalized": "1.22.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-01-07T16:49:33+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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" + ] + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.22.1", + "version_normalized": "1.22.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91", + "reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "time": "2021-01-07T16:49:33+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.22-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "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": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/process", + "version": "v3.4.47", + "version_normalized": "3.4.47.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "reference": "b8648cf1d5af12a44a51d07ef9bf980921f15fca", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "time": "2020-10-24T10:57:07+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Symfony Process Component", + "homepage": "https://symfony.com" + }, + { + "name": "webmozart/assert", + "version": "1.10.0", + "version_normalized": "1.10.0.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/6964c76c7804814a842473e0c8fd15bab0f18e25", + "reference": "6964c76c7804814a842473e0c8fd15bab0f18e25", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "time": "2021-03-09T10:59:23+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ] + } +] diff --git a/www/multitube/vendor/doctrine/annotations/CHANGELOG.md b/www/multitube/vendor/doctrine/annotations/CHANGELOG.md new file mode 100644 index 0000000..0b0ba1a --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/CHANGELOG.md @@ -0,0 +1,162 @@ +## Changelog + +### 1.6.1 + +This release fixes an issue in which annotations such as `@foo-bar` +and `@foo-` were incorrectly recognised as valid, and both erroneously +parsed as `@foo`. + +Any annotation with `@name-*` format will now silently be ignored, +allowing vendor-specific annotations to be prefixed with the tool +name. + +Total issues resolved: **3** + +- [165: Update the composer branch alias](https://github.com/doctrine/annotations/pull/165) thanks to @mikeSimonson +- [209: Change Annotation::value typehint to mixed](https://github.com/doctrine/annotations/pull/209) thanks to @malarzm +- [257: Skip parsing annotations containing dashes, such as `@Foo-bar`, or `@Foo-`](https://github.com/doctrine/annotations/pull/257) thanks to @Ocramius + +### 1.6.0 + +This release brings a new endpoint that make sure that you can't shoot yourself in the foot by calling ```registerLoader``` multiple times and a few tests improvements. + +Total issues resolved: **7** + +- [145: Memory leak in AnnotationRegistry::registerLoader() when called multiple times](https://github.com/doctrine/annotations/issues/145) thanks to @TriAnMan +- [146: Import error on @experimental Annotation](https://github.com/doctrine/annotations/issues/146) thanks to @aturki +- [147: Ignoring @experimental annotation used by Symfony 3.3 CacheAdapter](https://github.com/doctrine/annotations/pull/147) thanks to @aturki +- [151: Remove duplicate code in `DCOM58Test`](https://github.com/doctrine/annotations/pull/151) thanks to @tuanphpvn +- [161: Prevent loading class_exists multiple times](https://github.com/doctrine/annotations/pull/161) thanks to @jrjohnson +- [162: Add registerUniqueLoader to AnnotationRegistry](https://github.com/doctrine/annotations/pull/162) thanks to @jrjohnson +- [163: Use assertDirectoryExists and assertDirectoryNotExists](https://github.com/doctrine/annotations/pull/163) thanks to @carusogabriel + +Thanks to everyone involved in this release. + +### 1.5.0 + +This release increments the minimum supported PHP version to 7.1.0. + +Also, HHVM official support has been dropped. + +Some noticeable performance improvements to annotation autoloading +have been applied, making failed annotation autoloading less heavy +on the filesystem access. + +- [133: Add @throws annotation in AnnotationReader#__construct()](https://github.com/doctrine/annotations/issues/133) thanks to @SenseException +- [134: Require PHP 7.1, drop HHVM support](https://github.com/doctrine/annotations/issues/134) thanks to @lcobucci +- [135: Prevent the same loader from being registered twice](https://github.com/doctrine/annotations/issues/135) thanks to @jrjohnson +- [137: #135 optimise multiple class load attempts in AnnotationRegistry](https://github.com/doctrine/annotations/issues/137) thanks to @Ocramius + + +### 1.4.0 + +This release fix an issue were some annotations could be not loaded if the namespace in the use statement started with a backslash. +It also update the tests and drop the support for php 5.X + +- [115: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/issues/115) thanks to @pascalporedda +- [120: Missing annotations with the latest composer version](https://github.com/doctrine/annotations/pull/120) thanks to @gnat42 +- [121: Adding a more detailed explanation of the test](https://github.com/doctrine/annotations/pull/121) thanks to @mikeSimonson +- [101: Test annotation parameters containing space](https://github.com/doctrine/annotations/pull/101) thanks to @mikeSimonson +- [111: Cleanup: move to correct phpunit assertions](https://github.com/doctrine/annotations/pull/111) thanks to @Ocramius +- [112: Removes support for PHP 5.x](https://github.com/doctrine/annotations/pull/112) thanks to @railto +- [113: bumped phpunit version to 5.7](https://github.com/doctrine/annotations/pull/113) thanks to @gabbydgab +- [114: Enhancement: Use SVG Travis build badge](https://github.com/doctrine/annotations/pull/114) thanks to @localheinz +- [118: Integrating PHPStan](https://github.com/doctrine/annotations/pull/118) thanks to @ondrejmirtes + +### 1.3.1 - 2016-12-30 + +This release fixes an issue with ignored annotations that were already +autoloaded, causing the `SimpleAnnotationReader` to pick them up +anyway. [#110](https://github.com/doctrine/annotations/pull/110) + +Additionally, an issue was fixed in the `CachedReader`, which was +not correctly checking the freshness of cached annotations when +traits were defined on a class. [#105](https://github.com/doctrine/annotations/pull/105) + +Total issues resolved: **2** + +- [105: Return single max timestamp](https://github.com/doctrine/annotations/pull/105) +- [110: setIgnoreNotImportedAnnotations(true) didn’t work for existing classes](https://github.com/doctrine/annotations/pull/110) + +### 1.3.0 + +This release introduces a PHP version bump. `doctrine/annotations` now requires PHP +5.6 or later to be installed. + +A series of additional improvements have been introduced: + + * support for PHP 7 "grouped use statements" + * support for ignoring entire namespace names + via `Doctrine\Common\Annotations\AnnotationReader::addGlobalIgnoredNamespace()` and + `Doctrine\Common\Annotations\DocParser::setIgnoredAnnotationNamespaces()`. This will + allow you to ignore annotations from namespaces that you cannot autoload + * testing all parent classes and interfaces when checking if the annotation cache + in the `CachedReader` is fresh + * simplifying the cache keys used by the `CachedReader`: keys are no longer artificially + namespaced, since `Doctrine\Common\Cache` already supports that + * corrected parsing of multibyte strings when `mbstring.func_overload` is enabled + * corrected parsing of annotations when `"\t"` is put before the first annotation + in a docblock + * allow skipping non-imported annotations when a custom `DocParser` is passed to + the `AnnotationReader` constructor + +Total issues resolved: **15** + +- [45: DocParser can now ignore whole namespaces](https://github.com/doctrine/annotations/pull/45) +- [57: Switch to the docker-based infrastructure on Travis](https://github.com/doctrine/annotations/pull/57) +- [59: opcache.load_comments has been removed from PHP 7](https://github.com/doctrine/annotations/pull/59) +- [62: [CachedReader\ Test traits and parent class to see if cache is fresh](https://github.com/doctrine/annotations/pull/62) +- [65: Remove cache salt making key unnecessarily long](https://github.com/doctrine/annotations/pull/65) +- [66: Fix of incorrect parsing multibyte strings](https://github.com/doctrine/annotations/pull/66) +- [68: Annotations that are indented by tab are not processed.](https://github.com/doctrine/annotations/issues/68) +- [69: Support for Group Use Statements](https://github.com/doctrine/annotations/pull/69) +- [70: Allow tab character before first annotation in DocBlock](https://github.com/doctrine/annotations/pull/70) +- [74: Ignore not registered annotations fix](https://github.com/doctrine/annotations/pull/74) +- [92: Added tests for AnnotationRegistry class.](https://github.com/doctrine/annotations/pull/92) +- [96: Fix/#62 check trait and parent class ttl in annotations](https://github.com/doctrine/annotations/pull/96) +- [97: Feature - #45 - allow ignoring entire namespaces](https://github.com/doctrine/annotations/pull/97) +- [98: Enhancement/#65 remove cache salt from cached reader](https://github.com/doctrine/annotations/pull/98) +- [99: Fix - #70 - allow tab character before first annotation in docblock](https://github.com/doctrine/annotations/pull/99) + +### 1.2.4 + +Total issues resolved: **1** + +- [51: FileCacheReader::saveCacheFile::unlink fix](https://github.com/doctrine/annotations/pull/51) + +### 1.2.3 + +Total issues resolved: [**2**](https://github.com/doctrine/annotations/milestones/v1.2.3) + +- [49: #46 - applying correct `chmod()` to generated cache file](https://github.com/doctrine/annotations/pull/49) +- [50: Hotfix: match escaped quotes (revert #44)](https://github.com/doctrine/annotations/pull/50) + +### 1.2.2 + +Total issues resolved: **4** + +- [43: Exclude files from distribution with .gitattributes](https://github.com/doctrine/annotations/pull/43) +- [44: Update DocLexer.php](https://github.com/doctrine/annotations/pull/44) +- [46: A plain "file_put_contents" can cause havoc](https://github.com/doctrine/annotations/pull/46) +- [48: Deprecating the `FileCacheReader` in 1.2.2: will be removed in 2.0.0](https://github.com/doctrine/annotations/pull/48) + +### 1.2.1 + +Total issues resolved: **4** + +- [38: fixes doctrine/common#326](https://github.com/doctrine/annotations/pull/38) +- [39: Remove superfluous NS](https://github.com/doctrine/annotations/pull/39) +- [41: Warn if load_comments is not enabled.](https://github.com/doctrine/annotations/pull/41) +- [42: Clean up unused uses](https://github.com/doctrine/annotations/pull/42) + +### 1.2.0 + + * HHVM support + * Allowing dangling comma in annotations + * Excluded annotations are no longer autoloaded + * Importing namespaces also in traits + * Added support for `::class` 5.5-style constant, works also in 5.3 and 5.4 + +### 1.1.0 + + * Add Exception when ZendOptimizer+ or Opcache is configured to drop comments diff --git a/www/multitube/vendor/doctrine/annotations/LICENSE b/www/multitube/vendor/doctrine/annotations/LICENSE new file mode 100644 index 0000000..5e781fc --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2013 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/www/multitube/vendor/doctrine/annotations/README.md b/www/multitube/vendor/doctrine/annotations/README.md new file mode 100644 index 0000000..ddeddd2 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/README.md @@ -0,0 +1,22 @@ +# Doctrine Annotations + +[![Build Status](https://github.com/doctrine/annotations/workflows/Continuous%20Integration/badge.svg?label=build)](https://github.com/doctrine/persistence/actions) +[![Dependency Status](https://www.versioneye.com/package/php--doctrine--annotations/badge.png)](https://www.versioneye.com/package/php--doctrine--annotations) +[![Reference Status](https://www.versioneye.com/php/doctrine:annotations/reference_badge.svg)](https://www.versioneye.com/php/doctrine:annotations/references) +[![Total Downloads](https://poser.pugx.org/doctrine/annotations/downloads.png)](https://packagist.org/packages/doctrine/annotations) +[![Latest Stable Version](https://img.shields.io/packagist/v/doctrine/annotations.svg?label=stable)](https://packagist.org/packages/doctrine/annotations) + +Docblock Annotations Parser library (extracted from [Doctrine Common](https://github.com/doctrine/common)). + +## Documentation + +See the [doctrine-project website](https://www.doctrine-project.org/projects/doctrine-annotations/en/latest/index.html). + +## Contributing + +When making a pull request, make sure your changes follow the +[Coding Standard Guidelines](https://www.doctrine-project.org/projects/doctrine-coding-standard/en/current/reference/index.html#introduction). + +## Changelog + +See [CHANGELOG.md](CHANGELOG.md). diff --git a/www/multitube/vendor/doctrine/annotations/composer.json b/www/multitube/vendor/doctrine/annotations/composer.json new file mode 100644 index 0000000..e14ce93 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/composer.json @@ -0,0 +1,42 @@ +{ + "name": "doctrine/annotations", + "type": "library", + "description": "Docblock Annotations Parser", + "keywords": ["annotations", "docblock", "parser"], + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"}, + {"name": "Jonathan Wage", "email": "jonwage@gmail.com"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "^7.1 || ^8.0", + "ext-tokenizer": "*", + "doctrine/lexer": "1.*" + }, + "require-dev": { + "doctrine/cache": "1.*", + "doctrine/coding-standard": "^6.0 || ^8.1", + "phpstan/phpstan": "^0.12.20", + "phpunit/phpunit": "^7.5 || ^9.1.5" + }, + "config": { + "sort-packages": true + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" } + }, + "autoload-dev": { + "psr-4": { + "Doctrine\\Performance\\Common\\Annotations\\": "tests/Doctrine/Performance/Common/Annotations", + "Doctrine\\Tests\\Common\\Annotations\\": "tests/Doctrine/Tests/Common/Annotations" + }, + "files": [ + "tests/Doctrine/Tests/Common/Annotations/Fixtures/functions.php", + "tests/Doctrine/Tests/Common/Annotations/Fixtures/SingleClassLOC1000.php" + ] + } +} diff --git a/www/multitube/vendor/doctrine/annotations/docs/en/annotations.rst b/www/multitube/vendor/doctrine/annotations/docs/en/annotations.rst new file mode 100644 index 0000000..648ab26 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/docs/en/annotations.rst @@ -0,0 +1,271 @@ +Handling Annotations +==================== + +There are several different approaches to handling annotations in PHP. +Doctrine Annotations maps docblock annotations to PHP classes. Because +not all docblock annotations are used for metadata purposes a filter is +applied to ignore or skip classes that are not Doctrine annotations. + +Take a look at the following code snippet: + +.. code-block:: php + + namespace MyProject\Entities; + + use Doctrine\ORM\Mapping AS ORM; + use Symfony\Component\Validator\Constraints AS Assert; + + /** + * @author Benjamin Eberlei + * @ORM\Entity + * @MyProject\Annotations\Foobarable + */ + class User + { + /** + * @ORM\Id @ORM\Column @ORM\GeneratedValue + * @dummy + * @var int + */ + private $id; + + /** + * @ORM\Column(type="string") + * @Assert\NotEmpty + * @Assert\Email + * @var string + */ + private $email; + } + +In this snippet you can see a variety of different docblock annotations: + +- Documentation annotations such as ``@var`` and ``@author``. These + annotations are ignored and never considered for throwing an + exception due to wrongly used annotations. +- Annotations imported through use statements. The statement ``use + Doctrine\ORM\Mapping AS ORM`` makes all classes under that namespace + available as ``@ORM\ClassName``. Same goes for the import of + ``@Assert``. +- The ``@dummy`` annotation. It is not a documentation annotation and + not ignored. For Doctrine Annotations it is not entirely clear how + to handle this annotation. Depending on the configuration an exception + (unknown annotation) will be thrown when parsing this annotation. +- The fully qualified annotation ``@MyProject\Annotations\Foobarable``. + This is transformed directly into the given class name. + +How are these annotations loaded? From looking at the code you could +guess that the ORM Mapping, Assert Validation and the fully qualified +annotation can just be loaded using +the defined PHP autoloaders. This is not the case however: For error +handling reasons every check for class existence inside the +``AnnotationReader`` sets the second parameter $autoload +of ``class_exists($name, $autoload)`` to false. To work flawlessly the +``AnnotationReader`` requires silent autoloaders which many autoloaders are +not. Silent autoloading is NOT part of the `PSR-0 specification +`_ +for autoloading. + +This is why Doctrine Annotations uses its own autoloading mechanism +through a global registry. If you are wondering about the annotation +registry being global, there is no other way to solve the architectural +problems of autoloading annotation classes in a straightforward fashion. +Additionally if you think about PHP autoloading then you recognize it is +a global as well. + +To anticipate the configuration section, making the above PHP class work +with Doctrine Annotations requires this setup: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\AnnotationRegistry; + + AnnotationRegistry::registerFile("/path/to/doctrine/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php"); + AnnotationRegistry::registerAutoloadNamespace("Symfony\Component\Validator\Constraint", "/path/to/symfony/src"); + AnnotationRegistry::registerAutoloadNamespace("MyProject\Annotations", "/path/to/myproject/src"); + + $reader = new AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('dummy'); + +The second block with the annotation registry calls registers all the +three different annotation namespaces that are used. +Doctrine Annotations saves all its annotations in a single file, that is +why ``AnnotationRegistry#registerFile`` is used in contrast to +``AnnotationRegistry#registerAutoloadNamespace`` which creates a PSR-0 +compatible loading mechanism for class to file names. + +In the third block, we create the actual ``AnnotationReader`` instance. +Note that we also add ``dummy`` to the global list of ignored +annotations for which we do not throw exceptions. Setting this is +necessary in our example case, otherwise ``@dummy`` would trigger an +exception to be thrown during the parsing of the docblock of +``MyProject\Entities\User#id``. + +Setup and Configuration +----------------------- + +To use the annotations library is simple, you just need to create a new +``AnnotationReader`` instance: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + +This creates a simple annotation reader with no caching other than in +memory (in php arrays). Since parsing docblocks can be expensive you +should cache this process by using a caching reader. + +You can use a file caching reader, but please note it is deprecated to +do so: + +.. code-block:: php + + use Doctrine\Common\Annotations\FileCacheReader; + use Doctrine\Common\Annotations\AnnotationReader; + + $reader = new FileCacheReader( + new AnnotationReader(), + "/path/to/cache", + $debug = true + ); + +If you set the ``debug`` flag to ``true`` the cache reader will check +for changes in the original files, which is very important during +development. If you don't set it to ``true`` you have to delete the +directory to clear the cache. This gives faster performance, however +should only be used in production, because of its inconvenience during +development. + +You can also use one of the ``Doctrine\Common\Cache\Cache`` cache +implementations to cache the annotations: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\CachedReader; + use Doctrine\Common\Cache\ApcCache; + + $reader = new CachedReader( + new AnnotationReader(), + new ApcCache(), + $debug = true + ); + +The ``debug`` flag is used here as well to invalidate the cache files +when the PHP class with annotations changed and should be used during +development. + +.. warning :: + + The ``AnnotationReader`` works and caches under the + assumption that all annotations of a doc-block are processed at + once. That means that annotation classes that do not exist and + aren't loaded and cannot be autoloaded (using the + AnnotationRegistry) would never be visible and not accessible if a + cache is used unless the cache is cleared and the annotations + requested again, this time with all annotations defined. + +By default the annotation reader returns a list of annotations with +numeric indexes. If you want your annotations to be indexed by their +class name you can wrap the reader in an ``IndexedReader``: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\IndexedReader; + + $reader = new IndexedReader(new AnnotationReader()); + +.. warning:: + + You should never wrap the indexed reader inside a cached reader, + only the other way around. This way you can re-use the cache with + indexed or numeric keys, otherwise your code may experience failures + due to caching in a numerical or indexed format. + +Registering Annotations +~~~~~~~~~~~~~~~~~~~~~~~ + +As explained in the introduction, Doctrine Annotations uses its own +autoloading mechanism to determine if a given annotation has a +corresponding PHP class that can be autoloaded. For annotation +autoloading you have to configure the +``Doctrine\Common\Annotations\AnnotationRegistry``. There are three +different mechanisms to configure annotation autoloading: + +- Calling ``AnnotationRegistry#registerFile($file)`` to register a file + that contains one or more annotation classes. +- Calling ``AnnotationRegistry#registerNamespace($namespace, $dirs = + null)`` to register that the given namespace contains annotations and + that their base directory is located at the given $dirs or in the + include path if ``NULL`` is passed. The given directories should *NOT* + be the directory where classes of the namespace are in, but the base + directory of the root namespace. The AnnotationRegistry uses a + namespace to directory separator approach to resolve the correct path. +- Calling ``AnnotationRegistry#registerLoader($callable)`` to register + an autoloader callback. The callback accepts the class as first and + only parameter and has to return ``true`` if the corresponding file + was found and included. + +.. note:: + + Loaders have to fail silently, if a class is not found even if it + matches for example the namespace prefix of that loader. Never is a + loader to throw a warning or exception if the loading failed + otherwise parsing doc block annotations will become a huge pain. + +A sample loader callback could look like: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationRegistry; + use Symfony\Component\ClassLoader\UniversalClassLoader; + + AnnotationRegistry::registerLoader(function($class) { + $file = str_replace("\\", DIRECTORY_SEPARATOR, $class) . ".php"; + + if (file_exists("/my/base/path/" . $file)) { + // file_exists() makes sure that the loader fails silently + require "/my/base/path/" . $file; + } + }); + + $loader = new UniversalClassLoader(); + AnnotationRegistry::registerLoader(array($loader, "loadClass")); + + +Ignoring missing exceptions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default an exception is thrown from the ``AnnotationReader`` if an +annotation was found that: + +- is not part of the list of ignored "documentation annotations"; +- was not imported through a use statement; +- is not a fully qualified class that exists. + +You can disable this behavior for specific names if your docblocks do +not follow strict requirements: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + AnnotationReader::addGlobalIgnoredName('foo'); + +PHP Imports +~~~~~~~~~~~ + +By default the annotation reader parses the use-statement of a php file +to gain access to the import rules and register them for the annotation +processing. Only if you are using PHP Imports can you validate the +correct usage of annotations and throw exceptions if you misspelled an +annotation. This mechanism is enabled by default. + +To ease the upgrade path, we still allow you to disable this mechanism. +Note however that we will remove this in future versions: + +.. code-block:: php + + $reader = new \Doctrine\Common\Annotations\AnnotationReader(); + $reader->setEnabledPhpImports(false); diff --git a/www/multitube/vendor/doctrine/annotations/docs/en/custom.rst b/www/multitube/vendor/doctrine/annotations/docs/en/custom.rst new file mode 100644 index 0000000..11fbe1a --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/docs/en/custom.rst @@ -0,0 +1,443 @@ +Custom Annotation Classes +========================= + +If you want to define your own annotations, you just have to group them +in a namespace and register this namespace in the ``AnnotationRegistry``. +Annotation classes have to contain a class-level docblock with the text +``@Annotation``: + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** @Annotation */ + class Bar + { + // some code + } + +Inject annotation values +------------------------ + +The annotation parser checks if the annotation constructor has arguments, +if so then it will pass the value array, otherwise it will try to inject +values into public properties directly: + + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * + * Some Annotation using a constructor + */ + class Bar + { + private $foo; + + public function __construct(array $values) + { + $this->foo = $values['foo']; + } + } + + /** + * @Annotation + * + * Some Annotation without a constructor + */ + class Foo + { + public $bar; + } + +Optional: Constructors with Named Parameters +-------------------------------------------- + +Starting with Annotations v1.11 a new annotation instantiation strategy +is available that aims at compatibility of Annotation classes with the PHP 8 +attribute feature. You need to declare a constructor with regular parameter +names that match the named arguments in the annotation syntax. + +To enable this feature, you can tag your annotation class with +``@NamedArgumentConstructor`` (available from v1.12) or implement the +``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` interface +(available from v1.11 and deprecated as of v1.12). +When using the ``@NamedArgumentConstructor`` tag, the first argument of the +constructor is considered as the default one. + + +Usage with the ``@NamedArgumentContrustor`` tag + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @NamedArgumentConstructor + */ + class Bar implements NamedArgumentConstructorAnnotation + { + private $foo; + + public function __construct(string $foo) + { + $this->foo = $foo; + } + } + + /** Usable with @Bar(foo="baz") */ + /** Usable with @Bar("baz") */ + +In combination with PHP 8's constructor property promotion feature +you can simplify this to: + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @NamedArgumentConstructor + */ + class Bar implements NamedArgumentConstructorAnnotation + { + public function __construct(private string $foo) {} + } + + +Usage with the +``Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation`` +interface (v1.11, deprecated as of v1.12): +.. code-block:: php + + namespace MyCompany\Annotations; + + use Doctrine\Common\Annotations\NamedArgumentConstructorAnnotation; + + /** @Annotation */ + class Bar implements NamedArgumentConstructorAnnotation + { + private $foo; + + public function __construct(private string $foo) {} + } + + /** Usable with @Bar(foo="baz") */ + +Annotation Target +----------------- + +``@Target`` indicates the kinds of class elements to which an annotation +type is applicable. Then you could define one or more targets: + +- ``CLASS`` Allowed in class docblocks +- ``PROPERTY`` Allowed in property docblocks +- ``METHOD`` Allowed in the method docblocks +- ``FUNCTION`` Allowed in function dockblocks +- ``ALL`` Allowed in class, property, method and function docblocks +- ``ANNOTATION`` Allowed inside other annotations + +If the annotations is not allowed in the current context, an +``AnnotationException`` is thrown. + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + // some code + } + + /** + * @Annotation + * @Target("CLASS") + */ + class Foo + { + // some code + } + +Attribute types +--------------- + +The annotation parser checks the given parameters using the phpdoc +annotation ``@var``, The data type could be validated using the ``@var`` +annotation on the annotation properties or using the ``@Attributes`` and +``@Attribute`` annotations. + +If the data type does not match you get an ``AnnotationException`` + +.. code-block:: php + + namespace MyCompany\Annotations; + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + */ + class Bar + { + /** @var mixed */ + public $mixed; + + /** @var boolean */ + public $boolean; + + /** @var bool */ + public $bool; + + /** @var float */ + public $float; + + /** @var string */ + public $string; + + /** @var integer */ + public $integer; + + /** @var array */ + public $array; + + /** @var SomeAnnotationClass */ + public $annotation; + + /** @var array */ + public $arrayOfIntegers; + + /** @var array */ + public $arrayOfAnnotations; + } + + /** + * @Annotation + * @Target({"METHOD","PROPERTY"}) + * @Attributes({ + * @Attribute("stringProperty", type = "string"), + * @Attribute("annotProperty", type = "SomeAnnotationClass"), + * }) + */ + class Foo + { + public function __construct(array $values) + { + $this->stringProperty = $values['stringProperty']; + $this->annotProperty = $values['annotProperty']; + } + + // some code + } + +Annotation Required +------------------- + +``@Required`` indicates that the field must be specified when the +annotation is used. If it is not used you get an ``AnnotationException`` +stating that this value can not be null. + +Declaring a required field: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Foo + { + /** @Required */ + public $requiredField; + } + +Usage: + +.. code-block:: php + + /** @Foo(requiredField="value") */ + public $direction; // Valid + + /** @Foo */ + public $direction; // Required field missing, throws an AnnotationException + + +Enumerated values +----------------- + +- An annotation property marked with ``@Enum`` is a field that accepts a + fixed set of scalar values. +- You should use ``@Enum`` fields any time you need to represent fixed + values. +- The annotation parser checks the given value and throws an + ``AnnotationException`` if the value does not match. + + +Declaring an enumerated property: + +.. code-block:: php + + /** + * @Annotation + * @Target("ALL") + */ + class Direction + { + /** + * @Enum({"NORTH", "SOUTH", "EAST", "WEST"}) + */ + public $value; + } + +Annotation usage: + +.. code-block:: php + + /** @Direction("NORTH") */ + public $direction; // Valid value + + /** @Direction("NORTHEAST") */ + public $direction; // Invalid value, throws an AnnotationException + + +Constants +--------- + +The use of constants and class constants is available on the annotations +parser. + +The following usages are allowed: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + use MyCompany\Entity\SomeClass; + + /** + * @Foo(PHP_EOL) + * @Bar(Bar::FOO) + * @Foo({SomeClass::FOO, SomeClass::BAR}) + * @Bar({SomeClass::FOO_KEY = SomeClass::BAR_VALUE}) + */ + class User + { + } + + +Be careful with constants and the cache ! + +.. note:: + + The cached reader will not re-evaluate each time an annotation is + loaded from cache. When a constant is changed the cache must be + cleaned. + + +Usage +----- + +Using the library API is simple. Using the annotations described in the +previous section, you can now annotate other classes with your +annotations: + +.. code-block:: php + + namespace MyCompany\Entity; + + use MyCompany\Annotations\Foo; + use MyCompany\Annotations\Bar; + + /** + * @Foo(bar="foo") + * @Bar(foo="bar") + */ + class User + { + } + +Now we can write a script to get the annotations above: + +.. code-block:: php + + $reflClass = new ReflectionClass('MyCompany\Entity\User'); + $classAnnotations = $reader->getClassAnnotations($reflClass); + + foreach ($classAnnotations AS $annot) { + if ($annot instanceof \MyCompany\Annotations\Foo) { + echo $annot->bar; // prints "foo"; + } else if ($annot instanceof \MyCompany\Annotations\Bar) { + echo $annot->foo; // prints "bar"; + } + } + +You have a complete API for retrieving annotation class instances from a +class, property or method docblock: + + +Reader API +~~~~~~~~~~ + +Access all annotations of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotations(\ReflectionClass $class); + +Access one annotation of a class +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getClassAnnotation(\ReflectionClass $class, $annotationName); + +Access all annotations of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotations(\ReflectionMethod $method); + +Access one annotation of a method +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getMethodAnnotation(\ReflectionMethod $method, $annotationName); + +Access all annotations of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotations(\ReflectionProperty $property); + +Access one annotation of a property +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName); + +Access all annotations of a function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getFunctionAnnotations(\ReflectionFunction $property); + +Access one annotation of a function +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: php + + public function getFunctionAnnotation(\ReflectionFunction $property, $annotationName); diff --git a/www/multitube/vendor/doctrine/annotations/docs/en/index.rst b/www/multitube/vendor/doctrine/annotations/docs/en/index.rst new file mode 100644 index 0000000..fd001f4 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/docs/en/index.rst @@ -0,0 +1,101 @@ +Introduction +============ + +Doctrine Annotations allows to implement custom annotation +functionality for PHP classes and functions. + +.. code-block:: php + + class Foo + { + /** + * @MyAnnotation(myProperty="value") + */ + private $bar; + } + +Annotations aren't implemented in PHP itself which is why this component +offers a way to use the PHP doc-blocks as a place for the well known +annotation syntax using the ``@`` char. + +Annotations in Doctrine are used for the ORM configuration to build the +class mapping, but it can be used in other projects for other purposes +too. + +Installation +============ + +You can install the Annotation component with composer: + +.. code-block:: + +   $ composer require doctrine/annotations + +Create an annotation class +========================== + +An annotation class is a representation of the later used annotation +configuration in classes. The annotation class of the previous example +looks like this: + +.. code-block:: php + + /** + * @Annotation + */ + final class MyAnnotation + { + public $myProperty; + } + +The annotation class is declared as an annotation by ``@Annotation``. + +:ref:`Read more about custom annotations. ` + +Reading annotations +=================== + +The access to the annotations happens by reflection of the class or function +containing them. There are multiple reader-classes implementing the +``Doctrine\Common\Annotations\Reader`` interface, that can access the +annotations of a class. A common one is +``Doctrine\Common\Annotations\AnnotationReader``: + +.. code-block:: php + + use Doctrine\Common\Annotations\AnnotationReader; + use Doctrine\Common\Annotations\AnnotationRegistry; + + // Deprecated and will be removed in 2.0 but currently needed + AnnotationRegistry::registerLoader('class_exists'); + + $reflectionClass = new ReflectionClass(Foo::class); + $property = $reflectionClass->getProperty('bar'); + + $reader = new AnnotationReader(); + $myAnnotation = $reader->getPropertyAnnotation( + $property, + MyAnnotation::class + ); + + echo $myAnnotation->myProperty; // result: "value" + +Note that ``AnnotationRegistry::registerLoader('class_exists')`` only works +if you already have an autoloader configured (i.e. composer autoloader). +Otherwise, :ref:`please take a look to the other annotation autoload mechanisms `. + +A reader has multiple methods to access the annotations of a class or +function. + +:ref:`Read more about handling annotations. ` + +IDE Support +----------- + +Some IDEs already provide support for annotations: + +- Eclipse via the `Symfony2 Plugin `_ +- PhpStorm via the `PHP Annotations Plugin `_ or the `Symfony Plugin `_ + +.. _Read more about handling annotations.: annotations +.. _Read more about custom annotations.: custom diff --git a/www/multitube/vendor/doctrine/annotations/docs/en/sidebar.rst b/www/multitube/vendor/doctrine/annotations/docs/en/sidebar.rst new file mode 100644 index 0000000..6f5d13c --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/docs/en/sidebar.rst @@ -0,0 +1,6 @@ +.. toctree:: + :depth: 3 + + index + annotations + custom diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php new file mode 100644 index 0000000..750270e --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation.php @@ -0,0 +1,59 @@ + $data Key-value for properties to be defined in this class. + */ + final public function __construct(array $data) + { + foreach ($data as $key => $value) { + $this->$key = $value; + } + } + + /** + * Error handler for unknown property accessor in Annotation class. + * + * @param string $name Unknown property name. + * + * @throws BadMethodCallException + */ + public function __get($name) + { + throw new BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) + ); + } + + /** + * Error handler for unknown property mutator in Annotation class. + * + * @param string $name Unknown property name. + * @param mixed $value Property value. + * + * @throws BadMethodCallException + */ + public function __set($name, $value) + { + throw new BadMethodCallException( + sprintf("Unknown property '%s' on annotation '%s'.", $name, static::class) + ); + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php new file mode 100644 index 0000000..b1f8514 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Attribute.php @@ -0,0 +1,21 @@ + */ + public $value; +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php new file mode 100644 index 0000000..35d6410 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/Enum.php @@ -0,0 +1,69 @@ + */ + public $value; + + /** + * Literal target declaration. + * + * @var mixed[] + */ + public $literal; + + /** + * @throws InvalidArgumentException + * + * @phpstan-param array{literal?: mixed[], value: list} $values + */ + public function __construct(array $values) + { + if (! isset($values['literal'])) { + $values['literal'] = []; + } + + foreach ($values['value'] as $var) { + if (! is_scalar($var)) { + throw new InvalidArgumentException(sprintf( + '@Enum supports only scalar values "%s" given.', + is_object($var) ? get_class($var) : gettype($var) + )); + } + } + + foreach ($values['literal'] as $key => $var) { + if (! in_array($key, $values['value'])) { + throw new InvalidArgumentException(sprintf( + 'Undefined enumerator value "%s" for literal "%s".', + $key, + $var + )); + } + } + + $this->value = $values['value']; + $this->literal = $values['literal']; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php new file mode 100644 index 0000000..ae60f7d --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/IgnoreAnnotation.php @@ -0,0 +1,43 @@ + */ + public $names; + + /** + * @throws RuntimeException + * + * @phpstan-param array{value: string|list} $values + */ + public function __construct(array $values) + { + if (is_string($values['value'])) { + $values['value'] = [$values['value']]; + } + + if (! is_array($values['value'])) { + throw new RuntimeException(sprintf( + '@IgnoreAnnotation expects either a string name, or an array of strings, but got %s.', + json_encode($values['value']) + )); + } + + $this->names = $values['value']; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php new file mode 100644 index 0000000..1690601 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Annotation/NamedArgumentConstructor.php @@ -0,0 +1,13 @@ + */ + private static $map = [ + 'ALL' => self::TARGET_ALL, + 'CLASS' => self::TARGET_CLASS, + 'METHOD' => self::TARGET_METHOD, + 'PROPERTY' => self::TARGET_PROPERTY, + 'FUNCTION' => self::TARGET_FUNCTION, + 'ANNOTATION' => self::TARGET_ANNOTATION, + ]; + + /** @phpstan-var list */ + public $value; + + /** + * Targets as bitmask. + * + * @var int + */ + public $targets; + + /** + * Literal target declaration. + * + * @var string + */ + public $literal; + + /** + * @throws InvalidArgumentException + * + * @phpstan-param array{value?: string|list} $values + */ + public function __construct(array $values) + { + if (! isset($values['value'])) { + $values['value'] = null; + } + + if (is_string($values['value'])) { + $values['value'] = [$values['value']]; + } + + if (! is_array($values['value'])) { + throw new InvalidArgumentException( + sprintf( + '@Target expects either a string value, or an array of strings, "%s" given.', + is_object($values['value']) ? get_class($values['value']) : gettype($values['value']) + ) + ); + } + + $bitmask = 0; + foreach ($values['value'] as $literal) { + if (! isset(self::$map[$literal])) { + throw new InvalidArgumentException( + sprintf( + 'Invalid Target "%s". Available targets: [%s]', + $literal, + implode(', ', array_keys(self::$map)) + ) + ); + } + + $bitmask |= self::$map[$literal]; + } + + $this->targets = $bitmask; + $this->value = $values['value']; + $this->literal = implode(', ', $this->value); + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php new file mode 100644 index 0000000..b1ea64e --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php @@ -0,0 +1,171 @@ + $available + */ + public static function enumeratorError($attributeName, $annotationName, $context, $available, $given) + { + return new self(sprintf( + '[Enum Error] Attribute "%s" of @%s declared on %s accepts only [%s], but got %s.', + $attributeName, + $annotationName, + $context, + implode(', ', $available), + is_object($given) ? get_class($given) : $given + )); + } + + /** + * @return AnnotationException + */ + public static function optimizerPlusSaveComments() + { + return new self( + 'You have to enable opcache.save_comments=1 or zend_optimizerplus.save_comments=1.' + ); + } + + /** + * @return AnnotationException + */ + public static function optimizerPlusLoadComments() + { + return new self( + 'You have to enable opcache.load_comments=1 or zend_optimizerplus.load_comments=1.' + ); + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php new file mode 100644 index 0000000..1f538ee --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader.php @@ -0,0 +1,389 @@ + + */ + private static $globalImports = [ + 'ignoreannotation' => Annotation\IgnoreAnnotation::class, + ]; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNames = ImplicitlyIgnoredAnnotationNames::LIST; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names are case sensitive. + * + * @var array + */ + private static $globalIgnoredNamespaces = []; + + /** + * Add a new annotation to the globally ignored annotation names with regard to exception handling. + * + * @param string $name + */ + public static function addGlobalIgnoredName($name) + { + self::$globalIgnoredNames[$name] = true; + } + + /** + * Add a new annotation to the globally ignored annotation namespaces with regard to exception handling. + * + * @param string $namespace + */ + public static function addGlobalIgnoredNamespace($namespace) + { + self::$globalIgnoredNamespaces[$namespace] = true; + } + + /** + * Annotations parser. + * + * @var DocParser + */ + private $parser; + + /** + * Annotations parser used to collect parsing metadata. + * + * @var DocParser + */ + private $preParser; + + /** + * PHP parser used to collect imports. + * + * @var PhpParser + */ + private $phpParser; + + /** + * In-memory cache mechanism to store imported annotations per class. + * + * @psalm-var array<'class'|'function', array>> + */ + private $imports = []; + + /** + * In-memory cache mechanism to store ignored annotations per class. + * + * @psalm-var array<'class'|'function', array>> + */ + private $ignoredAnnotationNames = []; + + /** + * Initializes a new AnnotationReader. + * + * @throws AnnotationException + */ + public function __construct(?DocParser $parser = null) + { + if ( + extension_loaded('Zend Optimizer+') && (ini_get('zend_optimizerplus.save_comments') === '0' || + ini_get('opcache.save_comments') === '0') + ) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + if (extension_loaded('Zend OPcache') && ini_get('opcache.save_comments') === 0) { + throw AnnotationException::optimizerPlusSaveComments(); + } + + // Make sure that the IgnoreAnnotation annotation is loaded + class_exists(IgnoreAnnotation::class); + + $this->parser = $parser ?: new DocParser(); + + $this->preParser = new DocParser(); + + $this->preParser->setImports(self::$globalImports); + $this->preParser->setIgnoreNotImportedAnnotations(true); + $this->preParser->setIgnoredAnnotationNames(self::$globalIgnoredNames); + + $this->phpParser = new PhpParser(); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $this->parser->setTarget(Target::TARGET_CLASS); + $this->parser->setImports($this->getImports($class)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $context = 'property ' . $class->getName() . '::$' . $property->getName(); + + $this->parser->setTarget(Target::TARGET_PROPERTY); + $this->parser->setImports($this->getPropertyImports($property)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($property->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $context = 'method ' . $class->getName() . '::' . $method->getName() . '()'; + + $this->parser->setTarget(Target::TARGET_METHOD); + $this->parser->setImports($this->getMethodImports($method)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($class)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($method->getDocComment(), $context); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Gets the annotations applied to a function. + * + * @phpstan-return list An array of Annotations. + */ + public function getFunctionAnnotations(ReflectionFunction $function): array + { + $context = 'function ' . $function->getName(); + + $this->parser->setTarget(Target::TARGET_FUNCTION); + $this->parser->setImports($this->getImports($function)); + $this->parser->setIgnoredAnnotationNames($this->getIgnoredAnnotationNames($function)); + $this->parser->setIgnoredAnnotationNamespaces(self::$globalIgnoredNamespaces); + + return $this->parser->parse($function->getDocComment(), $context); + } + + /** + * Gets a function annotation. + * + * @return object|null The Annotation or NULL, if the requested annotation does not exist. + */ + public function getFunctionAnnotation(ReflectionFunction $function, string $annotationName) + { + $annotations = $this->getFunctionAnnotations($function); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Returns the ignored annotations for the given class or function. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @return array + */ + private function getIgnoredAnnotationNames($reflection): array + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + if (isset($this->ignoredAnnotationNames[$type][$name])) { + return $this->ignoredAnnotationNames[$type][$name]; + } + + $this->collectParsingMetadata($reflection); + + return $this->ignoredAnnotationNames[$type][$name]; + } + + /** + * Retrieves imports for a class or a function. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @return array + */ + private function getImports($reflection): array + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + if (isset($this->imports[$type][$name])) { + return $this->imports[$type][$name]; + } + + $this->collectParsingMetadata($reflection); + + return $this->imports[$type][$name]; + } + + /** + * Retrieves imports for methods. + * + * @return array + */ + private function getMethodImports(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $classImports = $this->getImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if ( + ! $trait->hasMethod($method->getName()) + || $trait->getFileName() !== $method->getFileName() + ) { + continue; + } + + $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); + } + + return array_merge($classImports, $traitImports); + } + + /** + * Retrieves imports for properties. + * + * @return array + */ + private function getPropertyImports(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $classImports = $this->getImports($class); + + $traitImports = []; + + foreach ($class->getTraits() as $trait) { + if (! $trait->hasProperty($property->getName())) { + continue; + } + + $traitImports = array_merge($traitImports, $this->phpParser->parseUseStatements($trait)); + } + + return array_merge($classImports, $traitImports); + } + + /** + * Collects parsing metadata for a given class or function. + * + * @param ReflectionClass|ReflectionFunction $reflection + */ + private function collectParsingMetadata($reflection): void + { + $type = $reflection instanceof ReflectionClass ? 'class' : 'function'; + $name = $reflection->getName(); + + $ignoredAnnotationNames = self::$globalIgnoredNames; + $annotations = $this->preParser->parse($reflection->getDocComment(), $type . ' ' . $name); + + foreach ($annotations as $annotation) { + if (! ($annotation instanceof IgnoreAnnotation)) { + continue; + } + + foreach ($annotation->names as $annot) { + $ignoredAnnotationNames[$annot] = true; + } + } + + $this->imports[$type][$name] = array_merge( + self::$globalImports, + $this->phpParser->parseUseStatements($reflection), + [ + '__NAMESPACE__' => $reflection->getNamespaceName(), + 'self' => $name, + ] + ); + + $this->ignoredAnnotationNames[$type][$name] = $ignoredAnnotationNames; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php new file mode 100644 index 0000000..259d497 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationRegistry.php @@ -0,0 +1,190 @@ +|null $dirs + */ + public static function registerAutoloadNamespace(string $namespace, $dirs = null): void + { + self::$autoloadNamespaces[$namespace] = $dirs; + } + + /** + * Registers multiple namespaces. + * + * Loading of this namespaces will be done with a PSR-0 namespace loading algorithm. + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + * + * @param string[][]|string[]|null[] $namespaces indexed by namespace name + */ + public static function registerAutoloadNamespaces(array $namespaces): void + { + self::$autoloadNamespaces = array_merge(self::$autoloadNamespaces, $namespaces); + } + + /** + * Registers an autoloading callable for annotations, much like spl_autoload_register(). + * + * NOTE: These class loaders HAVE to be silent when a class was not found! + * IMPORTANT: Loaders have to return true if they loaded a class that could contain the searched annotation class. + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + */ + public static function registerLoader(callable $callable): void + { + // Reset our static cache now that we have a new loader to work with + self::$failedToAutoload = []; + self::$loaders[] = $callable; + } + + /** + * Registers an autoloading callable for annotations, if it is not already registered + * + * @deprecated This method is deprecated and will be removed in + * doctrine/annotations 2.0. Annotations will be autoloaded in 2.0. + */ + public static function registerUniqueLoader(callable $callable): void + { + if (in_array($callable, self::$loaders, true)) { + return; + } + + self::registerLoader($callable); + } + + /** + * Autoloads an annotation class silently. + */ + public static function loadAnnotationClass(string $class): bool + { + if (class_exists($class, false)) { + return true; + } + + if (array_key_exists($class, self::$failedToAutoload)) { + return false; + } + + foreach (self::$autoloadNamespaces as $namespace => $dirs) { + if (strpos($class, $namespace) !== 0) { + continue; + } + + $file = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; + + if ($dirs === null) { + $path = stream_resolve_include_path($file); + if ($path) { + require $path; + + return true; + } + } else { + foreach ((array) $dirs as $dir) { + if (is_file($dir . DIRECTORY_SEPARATOR . $file)) { + require $dir . DIRECTORY_SEPARATOR . $file; + + return true; + } + } + } + } + + foreach (self::$loaders as $loader) { + if ($loader($class) === true) { + return true; + } + } + + if ( + self::$loaders === [] && + self::$autoloadNamespaces === [] && + self::$registerFileUsed === false && + class_exists($class) + ) { + return true; + } + + self::$failedToAutoload[$class] = null; + + return false; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php new file mode 100644 index 0000000..91fbad0 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/CachedReader.php @@ -0,0 +1,264 @@ +> */ + private $loadedAnnotations = []; + + /** @var int[] */ + private $loadedFilemtimes = []; + + /** + * @param bool $debug + */ + public function __construct(Reader $reader, Cache $cache, $debug = false) + { + $this->delegate = $reader; + $this->cache = $cache; + $this->debug = (bool) $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $cacheKey = $class->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getClassAnnotations($class); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + $cacheKey = $class->getName() . '$' . $property->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getPropertyAnnotations($property); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + $cacheKey = $class->getName() . '#' . $method->getName(); + + if (isset($this->loadedAnnotations[$cacheKey])) { + return $this->loadedAnnotations[$cacheKey]; + } + + $annots = $this->fetchFromCache($cacheKey, $class); + if ($annots === false) { + $annots = $this->delegate->getMethodAnnotations($method); + $this->saveToCache($cacheKey, $annots); + } + + return $this->loadedAnnotations[$cacheKey] = $annots; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + $this->loadedFilemtimes = []; + } + + /** + * Fetches a value from the cache. + * + * @param string $cacheKey The cache key. + * + * @return mixed The cached value or false when the value is not in cache. + */ + private function fetchFromCache($cacheKey, ReflectionClass $class) + { + $data = $this->cache->fetch($cacheKey); + if ($data !== false) { + if (! $this->debug || $this->isCacheFresh($cacheKey, $class)) { + return $data; + } + } + + return false; + } + + /** + * Saves a value to the cache. + * + * @param string $cacheKey The cache key. + * @param mixed $value The value. + * + * @return void + */ + private function saveToCache($cacheKey, $value) + { + $this->cache->save($cacheKey, $value); + if (! $this->debug) { + return; + } + + $this->cache->save('[C]' . $cacheKey, time()); + } + + /** + * Checks if the cache is fresh. + * + * @param string $cacheKey + * + * @return bool + */ + private function isCacheFresh($cacheKey, ReflectionClass $class) + { + $lastModification = $this->getLastModification($class); + if ($lastModification === 0) { + return true; + } + + return $this->cache->fetch('[C]' . $cacheKey) >= $lastModification; + } + + /** + * Returns the time the class was last modified, testing traits and parents + */ + private function getLastModification(ReflectionClass $class): int + { + $filename = $class->getFileName(); + + if (isset($this->loadedFilemtimes[$filename])) { + return $this->loadedFilemtimes[$filename]; + } + + $parent = $class->getParentClass(); + + $lastModification = max(array_merge( + [$filename ? filemtime($filename) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $class->getTraits()), + array_map(function (ReflectionClass $class): int { + return $this->getLastModification($class); + }, $class->getInterfaces()), + $parent ? [$this->getLastModification($parent)] : [] + )); + + assert($lastModification !== false); + + return $this->loadedFilemtimes[$filename] = $lastModification; + } + + private function getTraitLastModificationTime(ReflectionClass $reflectionTrait): int + { + $fileName = $reflectionTrait->getFileName(); + + if (isset($this->loadedFilemtimes[$fileName])) { + return $this->loadedFilemtimes[$fileName]; + } + + $lastModificationTime = max(array_merge( + [$fileName ? filemtime($fileName) : 0], + array_map(function (ReflectionClass $reflectionTrait): int { + return $this->getTraitLastModificationTime($reflectionTrait); + }, $reflectionTrait->getTraits()) + )); + + assert($lastModificationTime !== false); + + return $this->loadedFilemtimes[$fileName] = $lastModificationTime; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php new file mode 100644 index 0000000..f6567c5 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocLexer.php @@ -0,0 +1,129 @@ += 100 + public const T_IDENTIFIER = 100; + public const T_AT = 101; + public const T_CLOSE_CURLY_BRACES = 102; + public const T_CLOSE_PARENTHESIS = 103; + public const T_COMMA = 104; + public const T_EQUALS = 105; + public const T_FALSE = 106; + public const T_NAMESPACE_SEPARATOR = 107; + public const T_OPEN_CURLY_BRACES = 108; + public const T_OPEN_PARENTHESIS = 109; + public const T_TRUE = 110; + public const T_NULL = 111; + public const T_COLON = 112; + public const T_MINUS = 113; + + /** @var array */ + protected $noCase = [ + '@' => self::T_AT, + ',' => self::T_COMMA, + '(' => self::T_OPEN_PARENTHESIS, + ')' => self::T_CLOSE_PARENTHESIS, + '{' => self::T_OPEN_CURLY_BRACES, + '}' => self::T_CLOSE_CURLY_BRACES, + '=' => self::T_EQUALS, + ':' => self::T_COLON, + '-' => self::T_MINUS, + '\\' => self::T_NAMESPACE_SEPARATOR, + ]; + + /** @var array */ + protected $withCase = [ + 'true' => self::T_TRUE, + 'false' => self::T_FALSE, + 'null' => self::T_NULL, + ]; + + /** + * Whether the next token starts immediately, or if there were + * non-captured symbols before that + */ + public function nextTokenIsAdjacent(): bool + { + return $this->token === null + || ($this->lookahead !== null + && ($this->lookahead['position'] - $this->token['position']) === strlen($this->token['value'])); + } + + /** + * {@inheritdoc} + */ + protected function getCatchablePatterns() + { + return [ + '[a-z_\\\][a-z0-9_\:\\\]*[a-z_][a-z0-9_]*', + '(?:[+-]?[0-9]+(?:[\.][0-9]+)*)(?:[eE][+-]?[0-9]+)?', + '"(?:""|[^"])*+"', + ]; + } + + /** + * {@inheritdoc} + */ + protected function getNonCatchablePatterns() + { + return ['\s+', '\*+', '(.)']; + } + + /** + * {@inheritdoc} + */ + protected function getType(&$value) + { + $type = self::T_NONE; + + if ($value[0] === '"') { + $value = str_replace('""', '"', substr($value, 1, strlen($value) - 2)); + + return self::T_STRING; + } + + if (isset($this->noCase[$value])) { + return $this->noCase[$value]; + } + + if ($value[0] === '_' || $value[0] === '\\' || ctype_alpha($value[0])) { + return self::T_IDENTIFIER; + } + + $lowerValue = strtolower($value); + + if (isset($this->withCase[$lowerValue])) { + return $this->withCase[$lowerValue]; + } + + // Checking numeric value + if (is_numeric($value)) { + return strpos($value, '.') !== false || stripos($value, 'e') !== false + ? self::T_FLOAT : self::T_INTEGER; + } + + return $type; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php new file mode 100644 index 0000000..ae530c5 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php @@ -0,0 +1,1459 @@ + + */ + private static $classIdentifiers = [ + DocLexer::T_IDENTIFIER, + DocLexer::T_TRUE, + DocLexer::T_FALSE, + DocLexer::T_NULL, + ]; + + /** + * The lexer. + * + * @var DocLexer + */ + private $lexer; + + /** + * Current target context. + * + * @var int + */ + private $target; + + /** + * Doc parser used to collect annotation target. + * + * @var DocParser + */ + private static $metadataParser; + + /** + * Flag to control if the current annotation is nested or not. + * + * @var bool + */ + private $isNestedAnnotation = false; + + /** + * Hashmap containing all use-statements that are to be used when parsing + * the given doc block. + * + * @var array + */ + private $imports = []; + + /** + * This hashmap is used internally to cache results of class_exists() + * look-ups. + * + * @var array + */ + private $classExists = []; + + /** + * Whether annotations that have not been imported should be ignored. + * + * @var bool + */ + private $ignoreNotImportedAnnotations = false; + + /** + * An array of default namespaces if operating in simple mode. + * + * @var string[] + */ + private $namespaces = []; + + /** + * A list with annotations that are not causing exceptions when not resolved to an annotation class. + * + * The names must be the raw names as used in the class, not the fully qualified + * + * @var bool[] indexed by annotation name + */ + private $ignoredAnnotationNames = []; + + /** + * A list with annotations in namespaced format + * that are not causing exceptions when not resolved to an annotation class. + * + * @var bool[] indexed by namespace name + */ + private $ignoredAnnotationNamespaces = []; + + /** @var string */ + private $context = ''; + + /** + * Hash-map for caching annotation metadata. + * + * @var array + */ + private static $annotationMetadata = [ + Annotation\Target::class => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'has_named_argument_constructor' => false, + 'properties' => [], + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'attribute_types' => [ + 'value' => [ + 'required' => false, + 'type' => 'array', + 'array_type' => 'string', + 'value' => 'array', + ], + ], + ], + Annotation\Attribute::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_ANNOTATION', + 'targets' => Target::TARGET_ANNOTATION, + 'default_property' => 'name', + 'properties' => [ + 'name' => 'name', + 'type' => 'type', + 'required' => 'required', + ], + 'attribute_types' => [ + 'value' => [ + 'required' => true, + 'type' => 'string', + 'value' => 'string', + ], + 'type' => [ + 'required' => true, + 'type' => 'string', + 'value' => 'string', + ], + 'required' => [ + 'required' => false, + 'type' => 'boolean', + 'value' => 'boolean', + ], + ], + ], + Annotation\Attributes::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => 'value', + 'properties' => ['value' => 'value'], + 'attribute_types' => [ + 'value' => [ + 'type' => 'array', + 'required' => true, + 'array_type' => Annotation\Attribute::class, + 'value' => 'array<' . Annotation\Attribute::class . '>', + ], + ], + ], + Annotation\Enum::class => [ + 'is_annotation' => true, + 'has_constructor' => true, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_PROPERTY', + 'targets' => Target::TARGET_PROPERTY, + 'default_property' => 'value', + 'properties' => ['value' => 'value'], + 'attribute_types' => [ + 'value' => [ + 'type' => 'array', + 'required' => true, + ], + 'literal' => [ + 'type' => 'array', + 'required' => false, + ], + ], + ], + Annotation\NamedArgumentConstructor::class => [ + 'is_annotation' => true, + 'has_constructor' => false, + 'has_named_argument_constructor' => false, + 'targets_literal' => 'ANNOTATION_CLASS', + 'targets' => Target::TARGET_CLASS, + 'default_property' => null, + 'properties' => [], + 'attribute_types' => [], + ], + ]; + + /** + * Hash-map for handle types declaration. + * + * @var array + */ + private static $typeMap = [ + 'float' => 'double', + 'bool' => 'boolean', + // allow uppercase Boolean in honor of George Boole + 'Boolean' => 'boolean', + 'int' => 'integer', + ]; + + /** + * Constructs a new DocParser. + */ + public function __construct() + { + $this->lexer = new DocLexer(); + } + + /** + * Sets the annotation names that are ignored during the parsing process. + * + * The names are supposed to be the raw names as used in the class, not the + * fully qualified class names. + * + * @param bool[] $names indexed by annotation name + * + * @return void + */ + public function setIgnoredAnnotationNames(array $names) + { + $this->ignoredAnnotationNames = $names; + } + + /** + * Sets the annotation namespaces that are ignored during the parsing process. + * + * @param bool[] $ignoredAnnotationNamespaces indexed by annotation namespace name + * + * @return void + */ + public function setIgnoredAnnotationNamespaces($ignoredAnnotationNamespaces) + { + $this->ignoredAnnotationNamespaces = $ignoredAnnotationNamespaces; + } + + /** + * Sets ignore on not-imported annotations. + * + * @param bool $bool + * + * @return void + */ + public function setIgnoreNotImportedAnnotations($bool) + { + $this->ignoreNotImportedAnnotations = (bool) $bool; + } + + /** + * Sets the default namespaces. + * + * @param string $namespace + * + * @return void + * + * @throws RuntimeException + */ + public function addNamespace($namespace) + { + if ($this->imports) { + throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->namespaces[] = $namespace; + } + + /** + * Sets the imports. + * + * @param array $imports + * + * @return void + * + * @throws RuntimeException + */ + public function setImports(array $imports) + { + if ($this->namespaces) { + throw new RuntimeException('You must either use addNamespace(), or setImports(), but not both.'); + } + + $this->imports = $imports; + } + + /** + * Sets current target context as bitmask. + * + * @param int $target + * + * @return void + */ + public function setTarget($target) + { + $this->target = $target; + } + + /** + * Parses the given docblock string for annotations. + * + * @param string $input The docblock string to parse. + * @param string $context The parsing context. + * + * @throws AnnotationException + * @throws ReflectionException + * + * @phpstan-return list Array of annotations. If no annotations are found, an empty array is returned. + */ + public function parse($input, $context = '') + { + $pos = $this->findInitialTokenPosition($input); + if ($pos === null) { + return []; + } + + $this->context = $context; + + $this->lexer->setInput(trim(substr($input, $pos), '* /')); + $this->lexer->moveNext(); + + return $this->Annotations(); + } + + /** + * Finds the first valid annotation + * + * @param string $input The docblock string to parse + */ + private function findInitialTokenPosition($input): ?int + { + $pos = 0; + + // search for first valid annotation + while (($pos = strpos($input, '@', $pos)) !== false) { + $preceding = substr($input, $pos - 1, 1); + + // if the @ is preceded by a space, a tab or * it is valid + if ($pos === 0 || $preceding === ' ' || $preceding === '*' || $preceding === "\t") { + return $pos; + } + + $pos++; + } + + return null; + } + + /** + * Attempts to match the given token with the current lookahead token. + * If they match, updates the lookahead token; otherwise raises a syntax error. + * + * @param int $token Type of token. + * + * @return bool True if tokens match; false otherwise. + * + * @throws AnnotationException + */ + private function match(int $token): bool + { + if (! $this->lexer->isNextToken($token)) { + throw $this->syntaxError($this->lexer->getLiteral($token)); + } + + return $this->lexer->moveNext(); + } + + /** + * Attempts to match the current lookahead token with any of the given tokens. + * + * If any of them matches, this method updates the lookahead token; otherwise + * a syntax error is raised. + * + * @throws AnnotationException + * + * @phpstan-param list $tokens + */ + private function matchAny(array $tokens): bool + { + if (! $this->lexer->isNextTokenAny($tokens)) { + throw $this->syntaxError(implode(' or ', array_map([$this->lexer, 'getLiteral'], $tokens))); + } + + return $this->lexer->moveNext(); + } + + /** + * Generates a new syntax error. + * + * @param string $expected Expected string. + * @param mixed[]|null $token Optional token. + */ + private function syntaxError(string $expected, ?array $token = null): AnnotationException + { + if ($token === null) { + $token = $this->lexer->lookahead; + } + + $message = sprintf('Expected %s, got ', $expected); + $message .= $this->lexer->lookahead === null + ? 'end of string' + : sprintf("'%s' at position %s", $token['value'], $token['position']); + + if (strlen($this->context)) { + $message .= ' in ' . $this->context; + } + + $message .= '.'; + + return AnnotationException::syntaxError($message); + } + + /** + * Attempts to check if a class exists or not. This never goes through the PHP autoloading mechanism + * but uses the {@link AnnotationRegistry} to load classes. + * + * @param class-string $fqcn + */ + private function classExists(string $fqcn): bool + { + if (isset($this->classExists[$fqcn])) { + return $this->classExists[$fqcn]; + } + + // first check if the class already exists, maybe loaded through another AnnotationReader + if (class_exists($fqcn, false)) { + return $this->classExists[$fqcn] = true; + } + + // final check, does this class exist? + return $this->classExists[$fqcn] = AnnotationRegistry::loadAnnotationClass($fqcn); + } + + /** + * Collects parsing metadata for a given annotation class + * + * @param class-string $name The annotation name + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function collectAnnotationMetadata(string $name): void + { + if (self::$metadataParser === null) { + self::$metadataParser = new self(); + + self::$metadataParser->setIgnoreNotImportedAnnotations(true); + self::$metadataParser->setIgnoredAnnotationNames($this->ignoredAnnotationNames); + self::$metadataParser->setImports([ + 'enum' => Enum::class, + 'target' => Target::class, + 'attribute' => Attribute::class, + 'attributes' => Attributes::class, + 'namedargumentconstructor' => NamedArgumentConstructor::class, + ]); + + // Make sure that annotations from metadata are loaded + class_exists(Enum::class); + class_exists(Target::class); + class_exists(Attribute::class); + class_exists(Attributes::class); + class_exists(NamedArgumentConstructor::class); + } + + $class = new ReflectionClass($name); + $docComment = $class->getDocComment(); + + // Sets default values for annotation metadata + $constructor = $class->getConstructor(); + $metadata = [ + 'default_property' => null, + 'has_constructor' => $constructor !== null && $constructor->getNumberOfParameters() > 0, + 'constructor_args' => [], + 'properties' => [], + 'property_types' => [], + 'attribute_types' => [], + 'targets_literal' => null, + 'targets' => Target::TARGET_ALL, + 'is_annotation' => strpos($docComment, '@Annotation') !== false, + ]; + + $metadata['has_named_argument_constructor'] = $metadata['has_constructor'] + && $class->implementsInterface(NamedArgumentConstructorAnnotation::class); + + // verify that the class is really meant to be an annotation + if ($metadata['is_annotation']) { + self::$metadataParser->setTarget(Target::TARGET_CLASS); + + foreach (self::$metadataParser->parse($docComment, 'class @' . $name) as $annotation) { + if ($annotation instanceof Target) { + $metadata['targets'] = $annotation->targets; + $metadata['targets_literal'] = $annotation->literal; + + continue; + } + + if ($annotation instanceof NamedArgumentConstructor) { + $metadata['has_named_argument_constructor'] = $metadata['has_constructor']; + if ($metadata['has_named_argument_constructor']) { + // choose the first argument as the default property + $metadata['default_property'] = $constructor->getParameters()[0]->getName(); + } + } + + if (! ($annotation instanceof Attributes)) { + continue; + } + + foreach ($annotation->value as $attribute) { + $this->collectAttributeTypeMetadata($metadata, $attribute); + } + } + + // if not has a constructor will inject values into public properties + if ($metadata['has_constructor'] === false) { + // collect all public properties + foreach ($class->getProperties(ReflectionProperty::IS_PUBLIC) as $property) { + $metadata['properties'][$property->name] = $property->name; + + $propertyComment = $property->getDocComment(); + if ($propertyComment === false) { + continue; + } + + $attribute = new Attribute(); + + $attribute->required = (strpos($propertyComment, '@Required') !== false); + $attribute->name = $property->name; + $attribute->type = (strpos($propertyComment, '@var') !== false && + preg_match('/@var\s+([^\s]+)/', $propertyComment, $matches)) + ? $matches[1] + : 'mixed'; + + $this->collectAttributeTypeMetadata($metadata, $attribute); + + // checks if the property has @Enum + if (strpos($propertyComment, '@Enum') === false) { + continue; + } + + $context = 'property ' . $class->name . '::$' . $property->name; + + self::$metadataParser->setTarget(Target::TARGET_PROPERTY); + + foreach (self::$metadataParser->parse($propertyComment, $context) as $annotation) { + if (! $annotation instanceof Enum) { + continue; + } + + $metadata['enum'][$property->name]['value'] = $annotation->value; + $metadata['enum'][$property->name]['literal'] = (! empty($annotation->literal)) + ? $annotation->literal + : $annotation->value; + } + } + + // choose the first property as default property + $metadata['default_property'] = reset($metadata['properties']); + } elseif ($metadata['has_named_argument_constructor']) { + foreach ($constructor->getParameters() as $parameter) { + $metadata['constructor_args'][$parameter->getName()] = [ + 'position' => $parameter->getPosition(), + 'default' => $parameter->isOptional() ? $parameter->getDefaultValue() : null, + ]; + } + } + } + + self::$annotationMetadata[$name] = $metadata; + } + + /** + * Collects parsing metadata for a given attribute. + * + * @param mixed[] $metadata + */ + private function collectAttributeTypeMetadata(array &$metadata, Attribute $attribute): void + { + // handle internal type declaration + $type = self::$typeMap[$attribute->type] ?? $attribute->type; + + // handle the case if the property type is mixed + if ($type === 'mixed') { + return; + } + + // Evaluate type + $pos = strpos($type, '<'); + if ($pos !== false) { + // Checks if the property has array + $arrayType = substr($type, $pos + 1, -1); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + } else { + // Checks if the property has type[] + $pos = strrpos($type, '['); + if ($pos !== false) { + $arrayType = substr($type, 0, $pos); + $type = 'array'; + + if (isset(self::$typeMap[$arrayType])) { + $arrayType = self::$typeMap[$arrayType]; + } + + $metadata['attribute_types'][$attribute->name]['array_type'] = $arrayType; + } + } + + $metadata['attribute_types'][$attribute->name]['type'] = $type; + $metadata['attribute_types'][$attribute->name]['value'] = $attribute->type; + $metadata['attribute_types'][$attribute->name]['required'] = $attribute->required; + } + + /** + * Annotations ::= Annotation {[ "*" ]* [Annotation]}* + * + * @throws AnnotationException + * @throws ReflectionException + * + * @phpstan-return list + */ + private function Annotations(): array + { + $annotations = []; + + while ($this->lexer->lookahead !== null) { + if ($this->lexer->lookahead['type'] !== DocLexer::T_AT) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is preceded by non-catchable pattern + if ( + $this->lexer->token !== null && + $this->lexer->lookahead['position'] === $this->lexer->token['position'] + strlen( + $this->lexer->token['value'] + ) + ) { + $this->lexer->moveNext(); + continue; + } + + // make sure the @ is followed by either a namespace separator, or + // an identifier token + $peek = $this->lexer->glimpse(); + if ( + ($peek === null) + || ($peek['type'] !== DocLexer::T_NAMESPACE_SEPARATOR && ! in_array( + $peek['type'], + self::$classIdentifiers, + true + )) + || $peek['position'] !== $this->lexer->lookahead['position'] + 1 + ) { + $this->lexer->moveNext(); + continue; + } + + $this->isNestedAnnotation = false; + $annot = $this->Annotation(); + if ($annot === false) { + continue; + } + + $annotations[] = $annot; + } + + return $annotations; + } + + /** + * Annotation ::= "@" AnnotationName MethodCall + * AnnotationName ::= QualifiedName | SimpleName + * QualifiedName ::= NameSpacePart "\" {NameSpacePart "\"}* SimpleName + * NameSpacePart ::= identifier | null | false | true + * SimpleName ::= identifier | null | false | true + * + * @return object|false False if it is not a valid annotation. + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Annotation() + { + $this->match(DocLexer::T_AT); + + // check if we have an annotation + $name = $this->Identifier(); + + if ( + $this->lexer->isNextToken(DocLexer::T_MINUS) + && $this->lexer->nextTokenIsAdjacent() + ) { + // Annotations with dashes, such as "@foo-" or "@foo-bar", are to be discarded + return false; + } + + // only process names which are not fully qualified, yet + // fully qualified names must start with a \ + $originalName = $name; + + if ($name[0] !== '\\') { + $pos = strpos($name, '\\'); + $alias = ($pos === false) ? $name : substr($name, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + if ($this->namespaces) { + foreach ($this->namespaces as $namespace) { + if ($this->classExists($namespace . '\\' . $name)) { + $name = $namespace . '\\' . $name; + $found = true; + break; + } + } + } elseif (isset($this->imports[$loweredAlias])) { + $namespace = ltrim($this->imports[$loweredAlias], '\\'); + $name = ($pos !== false) + ? $namespace . substr($name, $pos) + : $namespace; + $found = $this->classExists($name); + } elseif ( + ! isset($this->ignoredAnnotationNames[$name]) + && isset($this->imports['__NAMESPACE__']) + && $this->classExists($this->imports['__NAMESPACE__'] . '\\' . $name) + ) { + $name = $this->imports['__NAMESPACE__'] . '\\' . $name; + $found = true; + } elseif (! isset($this->ignoredAnnotationNames[$name]) && $this->classExists($name)) { + $found = true; + } + + if (! $found) { + if ($this->isIgnoredAnnotation($name)) { + return false; + } + + throw AnnotationException::semanticalError(sprintf( + <<<'EXCEPTION' +The annotation "@%s" in %s was never imported. Did you maybe forget to add a "use" statement for this annotation? +EXCEPTION + , + $name, + $this->context + )); + } + } + + $name = ltrim($name, '\\'); + + if (! $this->classExists($name)) { + throw AnnotationException::semanticalError(sprintf( + 'The annotation "@%s" in %s does not exist, or could not be auto-loaded.', + $name, + $this->context + )); + } + + // at this point, $name contains the fully qualified class name of the + // annotation, and it is also guaranteed that this class exists, and + // that it is loaded + + // collects the metadata annotation only if there is not yet + if (! isset(self::$annotationMetadata[$name])) { + $this->collectAnnotationMetadata($name); + } + + // verify that the class is really meant to be an annotation and not just any ordinary class + if (self::$annotationMetadata[$name]['is_annotation'] === false) { + if ($this->isIgnoredAnnotation($originalName) || $this->isIgnoredAnnotation($name)) { + return false; + } + + throw AnnotationException::semanticalError(sprintf( + <<<'EXCEPTION' +The class "%s" is not annotated with @Annotation. +Are you sure this class can be used as annotation? +If so, then you need to add @Annotation to the _class_ doc comment of "%s". +If it is indeed no annotation, then you need to add @IgnoreAnnotation("%s") to the _class_ doc comment of %s. +EXCEPTION + , + $name, + $name, + $originalName, + $this->context + )); + } + + //if target is nested annotation + $target = $this->isNestedAnnotation ? Target::TARGET_ANNOTATION : $this->target; + + // Next will be nested + $this->isNestedAnnotation = true; + + //if annotation does not support current target + if ((self::$annotationMetadata[$name]['targets'] & $target) === 0 && $target) { + throw AnnotationException::semanticalError( + sprintf( + <<<'EXCEPTION' +Annotation @%s is not allowed to be declared on %s. You may only use this annotation on these code elements: %s. +EXCEPTION + , + $originalName, + $this->context, + self::$annotationMetadata[$name]['targets_literal'] + ) + ); + } + + $arguments = $this->MethodCall(); + $values = $this->resolvePositionalValues($arguments, $name); + + if (isset(self::$annotationMetadata[$name]['enum'])) { + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['enum'] as $property => $enum) { + // checks if the attribute is a valid enumerator + if (isset($values[$property]) && ! in_array($values[$property], $enum['value'])) { + throw AnnotationException::enumeratorError( + $property, + $name, + $this->context, + $enum['literal'], + $values[$property] + ); + } + } + } + + // checks all declared attributes + foreach (self::$annotationMetadata[$name]['attribute_types'] as $property => $type) { + if ( + $property === self::$annotationMetadata[$name]['default_property'] + && ! isset($values[$property]) && isset($values['value']) + ) { + $property = 'value'; + } + + // handle a not given attribute or null value + if (! isset($values[$property])) { + if ($type['required']) { + throw AnnotationException::requiredError( + $property, + $originalName, + $this->context, + 'a(n) ' . $type['value'] + ); + } + + continue; + } + + if ($type['type'] === 'array') { + // handle the case of a single value + if (! is_array($values[$property])) { + $values[$property] = [$values[$property]]; + } + + // checks if the attribute has array type declaration, such as "array" + if (isset($type['array_type'])) { + foreach ($values[$property] as $item) { + if (gettype($item) !== $type['array_type'] && ! $item instanceof $type['array_type']) { + throw AnnotationException::attributeTypeError( + $property, + $originalName, + $this->context, + 'either a(n) ' . $type['array_type'] . ', or an array of ' . $type['array_type'] . 's', + $item + ); + } + } + } + } elseif (gettype($values[$property]) !== $type['type'] && ! $values[$property] instanceof $type['type']) { + throw AnnotationException::attributeTypeError( + $property, + $originalName, + $this->context, + 'a(n) ' . $type['value'], + $values[$property] + ); + } + } + + if (self::$annotationMetadata[$name]['has_named_argument_constructor']) { + if (PHP_VERSION_ID >= 80000) { + return new $name(...$values); + } + + $positionalValues = []; + foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { + $positionalValues[$parameter['position']] = $parameter['default']; + } + + foreach ($values as $property => $value) { + if (! isset(self::$annotationMetadata[$name]['constructor_args'][$property])) { + throw AnnotationException::creationError(sprintf( + <<<'EXCEPTION' +The annotation @%s declared on %s does not have a property named "%s" +that can be set through its named arguments constructor. +Available named arguments: %s +EXCEPTION + , + $originalName, + $this->context, + $property, + implode(', ', array_keys(self::$annotationMetadata[$name]['constructor_args'])) + )); + } + + $positionalValues[self::$annotationMetadata[$name]['constructor_args'][$property]['position']] = $value; + } + + return new $name(...$positionalValues); + } + + // check if the annotation expects values via the constructor, + // or directly injected into public properties + if (self::$annotationMetadata[$name]['has_constructor'] === true) { + return new $name($values); + } + + $instance = new $name(); + + foreach ($values as $property => $value) { + if (! isset(self::$annotationMetadata[$name]['properties'][$property])) { + if ($property !== 'value') { + throw AnnotationException::creationError(sprintf( + <<<'EXCEPTION' +The annotation @%s declared on %s does not have a property named "%s". +Available properties: %s +EXCEPTION + , + $originalName, + $this->context, + $property, + implode(', ', self::$annotationMetadata[$name]['properties']) + )); + } + + // handle the case if the property has no annotations + $property = self::$annotationMetadata[$name]['default_property']; + if (! $property) { + throw AnnotationException::creationError(sprintf( + 'The annotation @%s declared on %s does not accept any values, but got %s.', + $originalName, + $this->context, + json_encode($values) + )); + } + } + + $instance->{$property} = $value; + } + + return $instance; + } + + /** + * MethodCall ::= ["(" [Values] ")"] + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function MethodCall(): array + { + $values = []; + + if (! $this->lexer->isNextToken(DocLexer::T_OPEN_PARENTHESIS)) { + return $values; + } + + $this->match(DocLexer::T_OPEN_PARENTHESIS); + + if (! $this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + $values = $this->Values(); + } + + $this->match(DocLexer::T_CLOSE_PARENTHESIS); + + return $values; + } + + /** + * Values ::= Array | Value {"," Value}* [","] + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Values(): array + { + $values = [$this->Value()]; + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_PARENTHESIS)) { + break; + } + + $token = $this->lexer->lookahead; + $value = $this->Value(); + + $values[] = $value; + } + + $namedArguments = []; + $positionalArguments = []; + foreach ($values as $k => $value) { + if (is_object($value) && $value instanceof stdClass) { + $namedArguments[$value->name] = $value->value; + } else { + $positionalArguments[$k] = $value; + } + } + + return ['named_arguments' => $namedArguments, 'positional_arguments' => $positionalArguments]; + } + + /** + * Constant ::= integer | string | float | boolean + * + * @return mixed + * + * @throws AnnotationException + */ + private function Constant() + { + $identifier = $this->Identifier(); + + if (! defined($identifier) && strpos($identifier, '::') !== false && $identifier[0] !== '\\') { + [$className, $const] = explode('::', $identifier); + + $pos = strpos($className, '\\'); + $alias = ($pos === false) ? $className : substr($className, 0, $pos); + $found = false; + $loweredAlias = strtolower($alias); + + switch (true) { + case ! empty($this->namespaces): + foreach ($this->namespaces as $ns) { + if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { + $className = $ns . '\\' . $className; + $found = true; + break; + } + } + + break; + + case isset($this->imports[$loweredAlias]): + $found = true; + $className = ($pos !== false) + ? $this->imports[$loweredAlias] . substr($className, $pos) + : $this->imports[$loweredAlias]; + break; + + default: + if (isset($this->imports['__NAMESPACE__'])) { + $ns = $this->imports['__NAMESPACE__']; + + if (class_exists($ns . '\\' . $className) || interface_exists($ns . '\\' . $className)) { + $className = $ns . '\\' . $className; + $found = true; + } + } + + break; + } + + if ($found) { + $identifier = $className . '::' . $const; + } + } + + /** + * Checks if identifier ends with ::class and remove the leading backslash if it exists. + */ + if ( + $this->identifierEndsWithClassConstant($identifier) && + ! $this->identifierStartsWithBackslash($identifier) + ) { + return substr($identifier, 0, $this->getClassConstantPositionInIdentifier($identifier)); + } + + if ($this->identifierEndsWithClassConstant($identifier) && $this->identifierStartsWithBackslash($identifier)) { + return substr($identifier, 1, $this->getClassConstantPositionInIdentifier($identifier) - 1); + } + + if (! defined($identifier)) { + throw AnnotationException::semanticalErrorConstants($identifier, $this->context); + } + + return constant($identifier); + } + + private function identifierStartsWithBackslash(string $identifier): bool + { + return $identifier[0] === '\\'; + } + + private function identifierEndsWithClassConstant(string $identifier): bool + { + return $this->getClassConstantPositionInIdentifier($identifier) === strlen($identifier) - strlen('::class'); + } + + /** + * @return int|false + */ + private function getClassConstantPositionInIdentifier(string $identifier) + { + return stripos($identifier, '::class'); + } + + /** + * Identifier ::= string + * + * @throws AnnotationException + */ + private function Identifier(): string + { + // check if we have an annotation + if (! $this->lexer->isNextTokenAny(self::$classIdentifiers)) { + throw $this->syntaxError('namespace separator or identifier'); + } + + $this->lexer->moveNext(); + + $className = $this->lexer->token['value']; + + while ( + $this->lexer->lookahead !== null && + $this->lexer->lookahead['position'] === ($this->lexer->token['position'] + + strlen($this->lexer->token['value'])) && + $this->lexer->isNextToken(DocLexer::T_NAMESPACE_SEPARATOR) + ) { + $this->match(DocLexer::T_NAMESPACE_SEPARATOR); + $this->matchAny(self::$classIdentifiers); + + $className .= '\\' . $this->lexer->token['value']; + } + + return $className; + } + + /** + * Value ::= PlainValue | FieldAssignment + * + * @return mixed + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Value() + { + $peek = $this->lexer->glimpse(); + + if ($peek['type'] === DocLexer::T_EQUALS) { + return $this->FieldAssignment(); + } + + return $this->PlainValue(); + } + + /** + * PlainValue ::= integer | string | float | boolean | Array | Annotation + * + * @return mixed + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function PlainValue() + { + if ($this->lexer->isNextToken(DocLexer::T_OPEN_CURLY_BRACES)) { + return $this->Arrayx(); + } + + if ($this->lexer->isNextToken(DocLexer::T_AT)) { + return $this->Annotation(); + } + + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + return $this->Constant(); + } + + switch ($this->lexer->lookahead['type']) { + case DocLexer::T_STRING: + $this->match(DocLexer::T_STRING); + + return $this->lexer->token['value']; + + case DocLexer::T_INTEGER: + $this->match(DocLexer::T_INTEGER); + + return (int) $this->lexer->token['value']; + + case DocLexer::T_FLOAT: + $this->match(DocLexer::T_FLOAT); + + return (float) $this->lexer->token['value']; + + case DocLexer::T_TRUE: + $this->match(DocLexer::T_TRUE); + + return true; + + case DocLexer::T_FALSE: + $this->match(DocLexer::T_FALSE); + + return false; + + case DocLexer::T_NULL: + $this->match(DocLexer::T_NULL); + + return null; + + default: + throw $this->syntaxError('PlainValue'); + } + } + + /** + * FieldAssignment ::= FieldName "=" PlainValue + * FieldName ::= identifier + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function FieldAssignment(): stdClass + { + $this->match(DocLexer::T_IDENTIFIER); + $fieldName = $this->lexer->token['value']; + + $this->match(DocLexer::T_EQUALS); + + $item = new stdClass(); + $item->name = $fieldName; + $item->value = $this->PlainValue(); + + return $item; + } + + /** + * Array ::= "{" ArrayEntry {"," ArrayEntry}* [","] "}" + * + * @return mixed[] + * + * @throws AnnotationException + * @throws ReflectionException + */ + private function Arrayx(): array + { + $array = $values = []; + + $this->match(DocLexer::T_OPEN_CURLY_BRACES); + + // If the array is empty, stop parsing and return. + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + return $array; + } + + $values[] = $this->ArrayEntry(); + + while ($this->lexer->isNextToken(DocLexer::T_COMMA)) { + $this->match(DocLexer::T_COMMA); + + // optional trailing comma + if ($this->lexer->isNextToken(DocLexer::T_CLOSE_CURLY_BRACES)) { + break; + } + + $values[] = $this->ArrayEntry(); + } + + $this->match(DocLexer::T_CLOSE_CURLY_BRACES); + + foreach ($values as $value) { + [$key, $val] = $value; + + if ($key !== null) { + $array[$key] = $val; + } else { + $array[] = $val; + } + } + + return $array; + } + + /** + * ArrayEntry ::= Value | KeyValuePair + * KeyValuePair ::= Key ("=" | ":") PlainValue | Constant + * Key ::= string | integer | Constant + * + * @throws AnnotationException + * @throws ReflectionException + * + * @phpstan-return array{mixed, mixed} + */ + private function ArrayEntry(): array + { + $peek = $this->lexer->glimpse(); + + if ( + $peek['type'] === DocLexer::T_EQUALS + || $peek['type'] === DocLexer::T_COLON + ) { + if ($this->lexer->isNextToken(DocLexer::T_IDENTIFIER)) { + $key = $this->Constant(); + } else { + $this->matchAny([DocLexer::T_INTEGER, DocLexer::T_STRING]); + $key = $this->lexer->token['value']; + } + + $this->matchAny([DocLexer::T_EQUALS, DocLexer::T_COLON]); + + return [$key, $this->PlainValue()]; + } + + return [null, $this->Value()]; + } + + /** + * Checks whether the given $name matches any ignored annotation name or namespace + */ + private function isIgnoredAnnotation(string $name): bool + { + if ($this->ignoreNotImportedAnnotations || isset($this->ignoredAnnotationNames[$name])) { + return true; + } + + foreach (array_keys($this->ignoredAnnotationNamespaces) as $ignoredAnnotationNamespace) { + $ignoredAnnotationNamespace = rtrim($ignoredAnnotationNamespace, '\\') . '\\'; + + if (stripos(rtrim($name, '\\') . '\\', $ignoredAnnotationNamespace) === 0) { + return true; + } + } + + return false; + } + + /** + * Resolve positional arguments (without name) to named ones + * + * @param array $arguments + * + * @return array + */ + private function resolvePositionalValues(array $arguments, string $name): array + { + $positionalArguments = $arguments['positional_arguments'] ?? []; + $values = $arguments['named_arguments'] ?? []; + + if ( + self::$annotationMetadata[$name]['has_named_argument_constructor'] + && self::$annotationMetadata[$name]['default_property'] !== null + ) { + // We must ensure that we don't have positional arguments after named ones + $positions = array_keys($positionalArguments); + $lastPosition = null; + foreach ($positions as $position) { + if ( + ($lastPosition === null && $position !== 0) || + ($lastPosition !== null && $position !== $lastPosition + 1) + ) { + throw $this->syntaxError('Positional arguments after named arguments is not allowed'); + } + + $lastPosition = $position; + } + + foreach (self::$annotationMetadata[$name]['constructor_args'] as $property => $parameter) { + $position = $parameter['position']; + if (isset($values[$property]) || ! isset($positionalArguments[$position])) { + continue; + } + + $values[$property] = $positionalArguments[$position]; + } + } else { + if (count($positionalArguments) > 0 && ! isset($values['value'])) { + if (count($positionalArguments) === 1) { + $value = array_pop($positionalArguments); + } else { + $value = array_values($positionalArguments); + } + + $values['value'] = $value; + } + } + + return $values; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php new file mode 100644 index 0000000..e6a7a95 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/FileCacheReader.php @@ -0,0 +1,315 @@ +> */ + private $loadedAnnotations = []; + + /** @var array */ + private $classNameHashes = []; + + /** @var int */ + private $umask; + + /** + * @param string $cacheDir + * @param bool $debug + * @param int $umask + * + * @throws InvalidArgumentException + */ + public function __construct(Reader $reader, $cacheDir, $debug = false, $umask = 0002) + { + if (! is_int($umask)) { + throw new InvalidArgumentException(sprintf( + 'The parameter umask must be an integer, was: %s', + gettype($umask) + )); + } + + $this->reader = $reader; + $this->umask = $umask; + + if (! is_dir($cacheDir) && ! @mkdir($cacheDir, 0777 & (~$this->umask), true)) { + throw new InvalidArgumentException(sprintf( + 'The directory "%s" does not exist and could not be created.', + $cacheDir + )); + } + + $this->dir = rtrim($cacheDir, '\\/'); + $this->debug = $debug; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name]; + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getClassAnnotations($class); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $class = $property->getDeclaringClass(); + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name] . '$' . $property->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getPropertyAnnotations($property); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $class = $method->getDeclaringClass(); + if (! isset($this->classNameHashes[$class->name])) { + $this->classNameHashes[$class->name] = sha1($class->name); + } + + $key = $this->classNameHashes[$class->name] . '#' . $method->getName(); + + if (isset($this->loadedAnnotations[$key])) { + return $this->loadedAnnotations[$key]; + } + + $path = $this->dir . '/' . strtr($key, '\\', '-') . '.cache.php'; + if (! is_file($path)) { + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + $filename = $class->getFilename(); + if ( + $this->debug + && $filename !== false + && filemtime($path) < filemtime($filename) + ) { + @unlink($path); + + $annot = $this->reader->getMethodAnnotations($method); + $this->saveCacheFile($path, $annot); + + return $this->loadedAnnotations[$key] = $annot; + } + + return $this->loadedAnnotations[$key] = include $path; + } + + /** + * Saves the cache file. + * + * @param string $path + * @param mixed $data + * + * @return void + */ + private function saveCacheFile($path, $data) + { + if (! is_writable($this->dir)) { + throw new InvalidArgumentException(sprintf( + <<<'EXCEPTION' +The directory "%s" is not writable. Both the webserver and the console user need access. +You can manage access rights for multiple users with "chmod +a". +If your system does not support this, check out the acl package., +EXCEPTION + , + $this->dir + )); + } + + $tempfile = tempnam($this->dir, uniqid('', true)); + + if ($tempfile === false) { + throw new RuntimeException(sprintf('Unable to create tempfile in directory: %s', $this->dir)); + } + + @chmod($tempfile, 0666 & (~$this->umask)); + + $written = file_put_contents( + $tempfile, + 'umask)); + + if (rename($tempfile, $path) === false) { + @unlink($tempfile); + + throw new RuntimeException(sprintf('Unable to rename %s to %s', $tempfile, $path)); + } + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + $annotations = $this->getClassAnnotations($class); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + $annotations = $this->getMethodAnnotations($method); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + $annotations = $this->getPropertyAnnotations($property); + + foreach ($annotations as $annotation) { + if ($annotation instanceof $annotationName) { + return $annotation; + } + } + + return null; + } + + /** + * Clears loaded annotations. + * + * @return void + */ + public function clearLoadedAnnotations() + { + $this->loadedAnnotations = []; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php new file mode 100644 index 0000000..52b929d --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/ImplicitlyIgnoredAnnotationNames.php @@ -0,0 +1,171 @@ + true, + 'Attribute' => true, + 'Attributes' => true, + /* Can we enable this? 'Enum' => true, */ + 'Required' => true, + 'Target' => true, + ]; + + private const WidelyUsedNonStandard = [ + 'fix' => true, + 'fixme' => true, + 'override' => true, + ]; + + private const PhpDocumentor1 = [ + 'abstract' => true, + 'access' => true, + 'code' => true, + 'deprec' => true, + 'endcode' => true, + 'exception' => true, + 'final' => true, + 'ingroup' => true, + 'inheritdoc' => true, + 'inheritDoc' => true, + 'magic' => true, + 'name' => true, + 'private' => true, + 'static' => true, + 'staticvar' => true, + 'staticVar' => true, + 'toc' => true, + 'tutorial' => true, + 'throw' => true, + ]; + + private const PhpDocumentor2 = [ + 'api' => true, + 'author' => true, + 'category' => true, + 'copyright' => true, + 'deprecated' => true, + 'example' => true, + 'filesource' => true, + 'global' => true, + 'ignore' => true, + /* Can we enable this? 'index' => true, */ + 'internal' => true, + 'license' => true, + 'link' => true, + 'method' => true, + 'package' => true, + 'param' => true, + 'property' => true, + 'property-read' => true, + 'property-write' => true, + 'return' => true, + 'see' => true, + 'since' => true, + 'source' => true, + 'subpackage' => true, + 'throws' => true, + 'todo' => true, + 'TODO' => true, + 'usedby' => true, + 'uses' => true, + 'var' => true, + 'version' => true, + ]; + + private const PHPUnit = [ + 'author' => true, + 'after' => true, + 'afterClass' => true, + 'backupGlobals' => true, + 'backupStaticAttributes' => true, + 'before' => true, + 'beforeClass' => true, + 'codeCoverageIgnore' => true, + 'codeCoverageIgnoreStart' => true, + 'codeCoverageIgnoreEnd' => true, + 'covers' => true, + 'coversDefaultClass' => true, + 'coversNothing' => true, + 'dataProvider' => true, + 'depends' => true, + 'doesNotPerformAssertions' => true, + 'expectedException' => true, + 'expectedExceptionCode' => true, + 'expectedExceptionMessage' => true, + 'expectedExceptionMessageRegExp' => true, + 'group' => true, + 'large' => true, + 'medium' => true, + 'preserveGlobalState' => true, + 'requires' => true, + 'runTestsInSeparateProcesses' => true, + 'runInSeparateProcess' => true, + 'small' => true, + 'test' => true, + 'testdox' => true, + 'testWith' => true, + 'ticket' => true, + 'uses' => true, + ]; + + private const PhpCheckStyle = ['SuppressWarnings' => true]; + + private const PhpStorm = ['noinspection' => true]; + + private const PEAR = ['package_version' => true]; + + private const PlainUML = [ + 'startuml' => true, + 'enduml' => true, + ]; + + private const Symfony = ['experimental' => true]; + + private const PhpCodeSniffer = [ + 'codingStandardsIgnoreStart' => true, + 'codingStandardsIgnoreEnd' => true, + ]; + + private const SlevomatCodingStandard = ['phpcsSuppress' => true]; + + private const PhpStan = [ + 'extends' => true, + 'implements' => true, + 'template' => true, + 'use' => true, + ]; + + private const Phan = ['suppress' => true]; + + private const Rector = ['noRector' => true]; + + public const LIST = self::Reserved + + self::WidelyUsedNonStandard + + self::PhpDocumentor1 + + self::PhpDocumentor2 + + self::PHPUnit + + self::PhpCheckStyle + + self::PhpStorm + + self::PEAR + + self::PlainUML + + self::Symfony + + self::SlevomatCodingStandard + + self::PhpCodeSniffer + + self::PhpStan + + self::Phan + + self::Rector; + + private function __construct() + { + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php new file mode 100644 index 0000000..42e7076 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/IndexedReader.php @@ -0,0 +1,100 @@ +delegate = $reader; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + $annotations = []; + foreach ($this->delegate->getClassAnnotations($class) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotation) + { + return $this->delegate->getClassAnnotation($class, $annotation); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + $annotations = []; + foreach ($this->delegate->getMethodAnnotations($method) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotation) + { + return $this->delegate->getMethodAnnotation($method, $annotation); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + $annotations = []; + foreach ($this->delegate->getPropertyAnnotations($property) as $annot) { + $annotations[get_class($annot)] = $annot; + } + + return $annotations; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotation) + { + return $this->delegate->getPropertyAnnotation($property, $annotation); + } + + /** + * Proxies all methods to the delegate. + * + * @param string $method + * @param mixed[] $args + * + * @return mixed + */ + public function __call($method, $args) + { + return call_user_func_array([$this->delegate, $method], $args); + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php new file mode 100644 index 0000000..8af224c --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/NamedArgumentConstructorAnnotation.php @@ -0,0 +1,14 @@ +ReflectionClass object. + * + * @return array A list with use statements in the form (Alias => FQN). + */ + public function parseClass(ReflectionClass $class) + { + return $this->parseUseStatements($class); + } + + /** + * Parse a class or function for use statements. + * + * @param ReflectionClass|ReflectionFunction $reflection + * + * @psalm-return array a list with use statements in the form (Alias => FQN). + */ + public function parseUseStatements($reflection): array + { + if (method_exists($reflection, 'getUseStatements')) { + return $reflection->getUseStatements(); + } + + $filename = $reflection->getFileName(); + + if ($filename === false) { + return []; + } + + $content = $this->getFileContent($filename, $reflection->getStartLine()); + + if ($content === null) { + return []; + } + + $namespace = preg_quote($reflection->getNamespaceName()); + $content = preg_replace('/^.*?(\bnamespace\s+' . $namespace . '\s*[;{].*)$/s', '\\1', $content); + $tokenizer = new TokenParser('parseUseStatements($reflection->getNamespaceName()); + } + + /** + * Gets the content of the file right up to the given line number. + * + * @param string $filename The name of the file to load. + * @param int $lineNumber The number of lines to read from file. + * + * @return string|null The content of the file or null if the file does not exist. + */ + private function getFileContent($filename, $lineNumber) + { + if (! is_file($filename)) { + return null; + } + + $content = ''; + $lineCnt = 0; + $file = new SplFileObject($filename); + while (! $file->eof()) { + if ($lineCnt++ === $lineNumber) { + break; + } + + $content .= $file->fgets(); + } + + return $content; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php new file mode 100644 index 0000000..0663ffd --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/Reader.php @@ -0,0 +1,80 @@ + An array of Annotations. + */ + public function getClassAnnotations(ReflectionClass $class); + + /** + * Gets a class annotation. + * + * @param ReflectionClass $class The ReflectionClass of the class from which + * the class annotations should be read. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName); + + /** + * Gets the annotations applied to a method. + * + * @param ReflectionMethod $method The ReflectionMethod of the method from which + * the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getMethodAnnotations(ReflectionMethod $method); + + /** + * Gets a method annotation. + * + * @param ReflectionMethod $method The ReflectionMethod to read the annotations from. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName); + + /** + * Gets the annotations applied to a property. + * + * @param ReflectionProperty $property The ReflectionProperty of the property + * from which the annotations should be read. + * + * @return array An array of Annotations. + */ + public function getPropertyAnnotations(ReflectionProperty $property); + + /** + * Gets a property annotation. + * + * @param ReflectionProperty $property The ReflectionProperty to read the annotations from. + * @param class-string $annotationName The name of the annotation. + * + * @return T|null The Annotation or NULL, if the requested annotation does not exist. + * + * @template T + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName); +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php new file mode 100644 index 0000000..8a78c11 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/SimpleAnnotationReader.php @@ -0,0 +1,114 @@ +parser = new DocParser(); + $this->parser->setIgnoreNotImportedAnnotations(true); + } + + /** + * Adds a namespace in which we will look for annotations. + * + * @param string $namespace + * + * @return void + */ + public function addNamespace($namespace) + { + $this->parser->addNamespace($namespace); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotations(ReflectionClass $class) + { + return $this->parser->parse($class->getDocComment(), 'class ' . $class->getName()); + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotations(ReflectionMethod $method) + { + return $this->parser->parse( + $method->getDocComment(), + 'method ' . $method->getDeclaringClass()->name . '::' . $method->getName() . '()' + ); + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotations(ReflectionProperty $property) + { + return $this->parser->parse( + $property->getDocComment(), + 'property ' . $property->getDeclaringClass()->name . '::$' . $property->getName() + ); + } + + /** + * {@inheritDoc} + */ + public function getClassAnnotation(ReflectionClass $class, $annotationName) + { + foreach ($this->getClassAnnotations($class) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getMethodAnnotation(ReflectionMethod $method, $annotationName) + { + foreach ($this->getMethodAnnotations($method) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } + + /** + * {@inheritDoc} + */ + public function getPropertyAnnotation(ReflectionProperty $property, $annotationName) + { + foreach ($this->getPropertyAnnotations($property) as $annot) { + if ($annot instanceof $annotationName) { + return $annot; + } + } + + return null; + } +} diff --git a/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php new file mode 100644 index 0000000..9605fb8 --- /dev/null +++ b/www/multitube/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/TokenParser.php @@ -0,0 +1,208 @@ + + */ + private $tokens; + + /** + * The number of tokens. + * + * @var int + */ + private $numTokens; + + /** + * The current array pointer. + * + * @var int + */ + private $pointer = 0; + + /** + * @param string $contents + */ + public function __construct($contents) + { + $this->tokens = token_get_all($contents); + + // The PHP parser sets internal compiler globals for certain things. Annoyingly, the last docblock comment it + // saw gets stored in doc_comment. When it comes to compile the next thing to be include()d this stored + // doc_comment becomes owned by the first thing the compiler sees in the file that it considers might have a + // docblock. If the first thing in the file is a class without a doc block this would cause calls to + // getDocBlock() on said class to return our long lost doc_comment. Argh. + // To workaround, cause the parser to parse an empty docblock. Sure getDocBlock() will return this, but at least + // it's harmless to us. + token_get_all("numTokens = count($this->tokens); + } + + /** + * Gets the next non whitespace and non comment token. + * + * @param bool $docCommentIsComment If TRUE then a doc comment is considered a comment and skipped. + * If FALSE then only whitespace and normal comments are skipped. + * + * @return mixed[]|string|null The token if exists, null otherwise. + */ + public function next($docCommentIsComment = true) + { + for ($i = $this->pointer; $i < $this->numTokens; $i++) { + $this->pointer++; + if ( + $this->tokens[$i][0] === T_WHITESPACE || + $this->tokens[$i][0] === T_COMMENT || + ($docCommentIsComment && $this->tokens[$i][0] === T_DOC_COMMENT) + ) { + continue; + } + + return $this->tokens[$i]; + } + + return null; + } + + /** + * Parses a single use statement. + * + * @return array A list with all found class names for a use statement. + */ + public function parseUseStatement() + { + $groupRoot = ''; + $class = ''; + $alias = ''; + $statements = []; + $explicitAlias = false; + while (($token = $this->next())) { + if (! $explicitAlias && $token[0] === T_STRING) { + $class .= $token[1]; + $alias = $token[1]; + } elseif ($explicitAlias && $token[0] === T_STRING) { + $alias = $token[1]; + } elseif ( + PHP_VERSION_ID >= 80000 && + ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) + ) { + $class .= $token[1]; + + $classSplit = explode('\\', $token[1]); + $alias = $classSplit[count($classSplit) - 1]; + } elseif ($token[0] === T_NS_SEPARATOR) { + $class .= '\\'; + $alias = ''; + } elseif ($token[0] === T_AS) { + $explicitAlias = true; + $alias = ''; + } elseif ($token === ',') { + $statements[strtolower($alias)] = $groupRoot . $class; + $class = ''; + $alias = ''; + $explicitAlias = false; + } elseif ($token === ';') { + $statements[strtolower($alias)] = $groupRoot . $class; + break; + } elseif ($token === '{') { + $groupRoot = $class; + $class = ''; + } elseif ($token === '}') { + continue; + } else { + break; + } + } + + return $statements; + } + + /** + * Gets all use statements. + * + * @param string $namespaceName The namespace name of the reflected class. + * + * @return array A list with all found use statements. + */ + public function parseUseStatements($namespaceName) + { + $statements = []; + while (($token = $this->next())) { + if ($token[0] === T_USE) { + $statements = array_merge($statements, $this->parseUseStatement()); + continue; + } + + if ($token[0] !== T_NAMESPACE || $this->parseNamespace() !== $namespaceName) { + continue; + } + + // Get fresh array for new namespace. This is to prevent the parser to collect the use statements + // for a previous namespace with the same name. This is the case if a namespace is defined twice + // or if a namespace with the same name is commented out. + $statements = []; + } + + return $statements; + } + + /** + * Gets the namespace. + * + * @return string The found namespace. + */ + public function parseNamespace() + { + $name = ''; + while ( + ($token = $this->next()) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR || ( + PHP_VERSION_ID >= 80000 && + ($token[0] === T_NAME_QUALIFIED || $token[0] === T_NAME_FULLY_QUALIFIED) + )) + ) { + $name .= $token[1]; + } + + return $name; + } + + /** + * Gets the class name. + * + * @return string The found class name. + */ + public function parseClass() + { + // Namespaces and class names are tokenized the same: T_STRINGs + // separated by T_NS_SEPARATOR so we can use one function to provide + // both. + return $this->parseNamespace(); + } +} diff --git a/www/multitube/vendor/doctrine/lexer/LICENSE b/www/multitube/vendor/doctrine/lexer/LICENSE new file mode 100644 index 0000000..e8fdec4 --- /dev/null +++ b/www/multitube/vendor/doctrine/lexer/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2006-2018 Doctrine Project + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/www/multitube/vendor/doctrine/lexer/README.md b/www/multitube/vendor/doctrine/lexer/README.md new file mode 100644 index 0000000..e1b419a --- /dev/null +++ b/www/multitube/vendor/doctrine/lexer/README.md @@ -0,0 +1,9 @@ +# Doctrine Lexer + +Build Status: [![Build Status](https://travis-ci.org/doctrine/lexer.svg?branch=master)](https://travis-ci.org/doctrine/lexer) + +Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers. + +This lexer is used in Doctrine Annotations and in Doctrine ORM (DQL). + +https://www.doctrine-project.org/projects/lexer.html diff --git a/www/multitube/vendor/doctrine/lexer/composer.json b/www/multitube/vendor/doctrine/lexer/composer.json new file mode 100644 index 0000000..3432bae --- /dev/null +++ b/www/multitube/vendor/doctrine/lexer/composer.json @@ -0,0 +1,41 @@ +{ + "name": "doctrine/lexer", + "type": "library", + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "keywords": [ + "php", + "parser", + "lexer", + "annotations", + "docblock" + ], + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "license": "MIT", + "authors": [ + {"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"}, + {"name": "Roman Borschel", "email": "roman@code-factory.org"}, + {"name": "Johannes Schmitt", "email": "schmittjoh@gmail.com"} + ], + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^6.0", + "phpstan/phpstan": "^0.11.8", + "phpunit/phpunit": "^8.2" + }, + "autoload": { + "psr-4": { "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer" } + }, + "autoload-dev": { + "psr-4": { "Doctrine\\Tests\\": "tests/Doctrine" } + }, + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "config": { + "sort-packages": true + } +} diff --git a/www/multitube/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php b/www/multitube/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php new file mode 100644 index 0000000..385643a --- /dev/null +++ b/www/multitube/vendor/doctrine/lexer/lib/Doctrine/Common/Lexer/AbstractLexer.php @@ -0,0 +1,328 @@ +input = $input; + $this->tokens = []; + + $this->reset(); + $this->scan($input); + } + + /** + * Resets the lexer. + * + * @return void + */ + public function reset() + { + $this->lookahead = null; + $this->token = null; + $this->peek = 0; + $this->position = 0; + } + + /** + * Resets the peek pointer to 0. + * + * @return void + */ + public function resetPeek() + { + $this->peek = 0; + } + + /** + * Resets the lexer position on the input to the given position. + * + * @param int $position Position to place the lexical scanner. + * + * @return void + */ + public function resetPosition($position = 0) + { + $this->position = $position; + } + + /** + * Retrieve the original lexer's input until a given position. + * + * @param int $position + * + * @return string + */ + public function getInputUntilPosition($position) + { + return substr($this->input, 0, $position); + } + + /** + * Checks whether a given token matches the current lookahead. + * + * @param int|string $token + * + * @return bool + */ + public function isNextToken($token) + { + return $this->lookahead !== null && $this->lookahead['type'] === $token; + } + + /** + * Checks whether any of the given tokens matches the current lookahead. + * + * @param array $tokens + * + * @return bool + */ + public function isNextTokenAny(array $tokens) + { + return $this->lookahead !== null && in_array($this->lookahead['type'], $tokens, true); + } + + /** + * Moves to the next token in the input string. + * + * @return bool + */ + public function moveNext() + { + $this->peek = 0; + $this->token = $this->lookahead; + $this->lookahead = isset($this->tokens[$this->position]) + ? $this->tokens[$this->position++] : null; + + return $this->lookahead !== null; + } + + /** + * Tells the lexer to skip input tokens until it sees a token with the given value. + * + * @param string $type The token type to skip until. + * + * @return void + */ + public function skipUntil($type) + { + while ($this->lookahead !== null && $this->lookahead['type'] !== $type) { + $this->moveNext(); + } + } + + /** + * Checks if given value is identical to the given token. + * + * @param mixed $value + * @param int|string $token + * + * @return bool + */ + public function isA($value, $token) + { + return $this->getType($value) === $token; + } + + /** + * Moves the lookahead token forward. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function peek() + { + if (isset($this->tokens[$this->position + $this->peek])) { + return $this->tokens[$this->position + $this->peek++]; + } + + return null; + } + + /** + * Peeks at the next token, returns it and immediately resets the peek. + * + * @return array|null The next token or NULL if there are no more tokens ahead. + */ + public function glimpse() + { + $peek = $this->peek(); + $this->peek = 0; + + return $peek; + } + + /** + * Scans the input string for tokens. + * + * @param string $input A query string. + * + * @return void + */ + protected function scan($input) + { + if (! isset($this->regex)) { + $this->regex = sprintf( + '/(%s)|%s/%s', + implode(')|(', $this->getCatchablePatterns()), + implode('|', $this->getNonCatchablePatterns()), + $this->getModifiers() + ); + } + + $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE; + $matches = preg_split($this->regex, $input, -1, $flags); + + if ($matches === false) { + // Work around https://bugs.php.net/78122 + $matches = [[$input, 0]]; + } + + foreach ($matches as $match) { + // Must remain before 'value' assignment since it can change content + $type = $this->getType($match[0]); + + $this->tokens[] = [ + 'value' => $match[0], + 'type' => $type, + 'position' => $match[1], + ]; + } + } + + /** + * Gets the literal for a given token. + * + * @param int|string $token + * + * @return int|string + */ + public function getLiteral($token) + { + $className = static::class; + $reflClass = new ReflectionClass($className); + $constants = $reflClass->getConstants(); + + foreach ($constants as $name => $value) { + if ($value === $token) { + return $className . '::' . $name; + } + } + + return $token; + } + + /** + * Regex modifiers + * + * @return string + */ + protected function getModifiers() + { + return 'iu'; + } + + /** + * Lexical catchable patterns. + * + * @return array + */ + abstract protected function getCatchablePatterns(); + + /** + * Lexical non-catchable patterns. + * + * @return array + */ + abstract protected function getNonCatchablePatterns(); + + /** + * Retrieve token type. Also processes the token value if necessary. + * + * @param string $value + * + * @return int|string|null + */ + abstract protected function getType(&$value); +} diff --git a/www/multitube/vendor/ipfs/php-client/.gitignore b/www/multitube/vendor/ipfs/php-client/.gitignore new file mode 100644 index 0000000..1250128 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/.gitignore @@ -0,0 +1,8 @@ +/bin/* +!bin/php-ipfs +!bin/rebuild +/vendor/ +/composer.phar +/coverage +coverage.xml +phpspec.yml \ No newline at end of file diff --git a/www/multitube/vendor/ipfs/php-client/.php_cs b/www/multitube/vendor/ipfs/php-client/.php_cs new file mode 100644 index 0000000..210c1c9 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/.php_cs @@ -0,0 +1,37 @@ + + +For the full copyright and license information, please view the LICENSE +file that was distributed with this source code. +EOF; + +$finder = PhpCsFixer\Finder::create() + ->exclude('vendor') + ->exclude('bin') + ->in(getenv('PWD')); // this may not be correct in a non-docker environment + +return PhpCsFixer\Config::create() + ->setRiskyAllowed(true) + ->setRules([ + '@Symfony' => true, + 'header_comment' => ['header' => $header], + '@PSR2' => true, + '@PSR1' => true, + 'array_syntax' => ['syntax' => 'short'], + 'ordered_imports' => true, + 'strict_comparison' => true, + 'strict_param' => true, + 'phpdoc_order' => true, + 'no_useless_return' => true, + 'ereg_to_preg' => true, + 'concat_space' => ['spacing' => 'one'], + 'binary_operator_spaces' => ['align_equals' => false, 'align_double_arrow' => true], + ]) +//->setUsingLinter(false) + ->setFinder($finder) + ->setUsingCache(false); diff --git a/www/multitube/vendor/ipfs/php-client/.travis.yml b/www/multitube/vendor/ipfs/php-client/.travis.yml new file mode 100644 index 0000000..001c322 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/.travis.yml @@ -0,0 +1,44 @@ +language: php + +sudo: false + +cache: + directories: + - $HOME/.composer/cache + +php: + - 7.0 + - 7.1 + - 7.2 + - nightly + +env: + global: + - TEST_COMMAND="composer test" + +matrix: + fast_finish: true + include: + - php: 7.0 + env: COMPOSER_FLAGS="--prefer-stable --prefer-lowest" TEST_COMMAND="composer coverage" COVERAGE=true" + - php: 7.0 + env: TEST_COMMAND="bin/rebuild" CS=true + - php: 7.0 + env: TEST_COMMAND="composer cs-check" CS=true + allow_failures: + - php: hhvm + +before_install: + - travis_retry composer self-update + - if [[ "$COVERAGE" = true ]]; then composer require --no-update --dev henrikbjorn/phpspec-code-coverage; fi + - if [[ "$CS" = true ]]; then composer global require friendsofphp/php-cs-fixer && export PATH="$PATH:$HOME/.composer/vendor/bin"; fi + +install: + - travis_retry composer update ${COMPOSER_FLAGS} --prefer-dist --no-interaction + +script: + - $TEST_COMMAND + +after_success: + - if [[ "$COVERAGE" = true ]]; then wget https://scrutinizer-ci.com/ocular.phar; fi + - if [[ "$COVERAGE" = true ]]; then php ocular.phar code-coverage:upload --format=php-clover coverage.xml; fi \ No newline at end of file diff --git a/www/multitube/vendor/ipfs/php-client/LICENSE b/www/multitube/vendor/ipfs/php-client/LICENSE new file mode 100644 index 0000000..8dad2ec --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Robert Schönthal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/www/multitube/vendor/ipfs/php-client/README.md b/www/multitube/vendor/ipfs/php-client/README.md new file mode 100644 index 0000000..5631db3 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/README.md @@ -0,0 +1,263 @@ +# PHP Adapter for IPFS + +![ipfs](https://user-images.githubusercontent.com/1211152/29604883-ca3a4028-87e0-11e7-9f9a-75de49b06048.png) + +Dont know what ipfs is? the future of filesystems :) read [here](https://ipfs.io) for more information! + +[![Build Status](https://travis-ci.org/digitalkaoz/php-ipfs-api.svg?branch=master)](https://travis-ci.org/digitalkaoz/php-ipfs-api) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/digitalkaoz/php-ipfs-api/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/digitalkaoz/php-ipfs-api/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/digitalkaoz/php-ipfs-api/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/digitalkaoz/php-ipfs-api/?branch=master) + +## Installation + +as always, use composer! +``` +$ composer require ipfs/php-client +``` + +### choosing the HTTP Adapter + +If you plan to use the REST Interface of the ipfs-daemon you should choose a http-implementation. We use [php-http](http://docs.php-http.org/) for abstraction. + +See [here](https://packagist.org/providers/php-http/async-client-implementation) for a list of available implementations! + +if you only want to speak with a local ipfs-daemon you should use the `IPFS\\Drivers\\Cli` adapter. + +### Annotations + +as we use Annotations you should register the `AnnotationLoader` + +```php +$loader = require __DIR__.'/../vendor/autoload.php'; + +use Doctrine\Common\Annotations\AnnotationRegistry; + +AnnotationRegistry::registerLoader(array($loader, "loadClass")); +``` + +## Drivers + +we ship with different adapters for communicating with the daemon. + +### CLI + +if you are using an `ipfs` binary that is not available in you `$PATH` variable, provide an `ENV` var for it: + +``` +$ export IPFS_BINARY=/my/location/to/ipfs +``` + +> make sure you set `IPFS_PATH` in you `ENV` if you are not using `~/.ipfs` as location. + +to use this Driver from the commandline simply provide the option: + +``` +$ bin/php-ipfs version --driver=IPFS\\Driver\\Cli +``` + +### HTTP + +if you are talking to a remote daemon provide an `ENV` var for it: + +``` +$ export IPFS_API=http://somehost:5001/api/v0 +``` + +to use this Driver from the commandline simply provide the option (or leave it away since its the default): + +``` +$ bin/php-ipfs version --driver=IPFS\\Driver\\Http +$ bin/php-ipfs version +``` + +### Client + +this Driver is intended for programmatically usage: + +```php +$driver = $container[IPFS\Driver\Cli::class]; +//$driver = $container[IPFS\Driver\Http::class]; +$client = new IPFS\Client($driver); + +$response = $client->execute((new \IPFS\Api\Basics())->version()); + +var_dump($response); +``` + +## Apis + +All Api-Endpoints are autogenerated from the official [ipfs docs](https://ipfs.io/docs/api/) and are regulary checked for changes. + +> To rebuild the Apis yourself, simply run `composer rebuild-api` + +The following endpoints exists: + +``` +Available commands: + add Add a file or directory to ipfs. + cat Show IPFS object data. + commands List all available commands. + dns Resolve DNS links. + get Download IPFS objects. + help Displays help for a command + id Show ipfs node id info. + list Lists commands + ls List directory contents for Unix filesystem objects. + mount Mounts IPFS to the filesystem (read-only). + ping Send echo request packets to IPFS hosts. + rebuild rebuild api classes by parsing the official api doc + resolve Resolve the value of names to IPFS. + shutdown Shut down the ipfs daemon. + update + version Show ipfs version information. + bitswap + bitswap:ledger Show the current ledger for a peer. + bitswap:reprovide Trigger reprovider. + bitswap:stat Show some diagnostic information on the bitswap agent. + bitswap:unwant Remove a given block from your wantlist. + bitswap:wantlist Show blocks currently on the wantlist. + block + block:get Get a raw IPFS block. + block:put Store input as an IPFS block. + block:rm Remove IPFS block(s). + block:stat Print information of a raw IPFS block. + bootstrap + bootstrap:add:default Add default peers to the bootstrap list. + bootstrap:list Show peers in the bootstrap list. + bootstrap:rm:all Remove all peers from the bootstrap list. + config + config:edit Open the config file for editing in $EDITOR. + config:profile:apply Apply profile to config. + config:replace Replace the config with . + config:show Output config file contents. + dag + dag:get Get a dag node from ipfs. + dag:put Add a dag node to ipfs. + dag:resolve Resolve ipld block. + dht + dht:findpeer Query the DHT for all of the multiaddresses associated with a Peer ID. + dht:findprovs Find peers in the DHT that can provide a specific value, given a key. + dht:get Given a key, query the DHT for its best value. + dht:provide Announce to the network that you are providing given values. + dht:put Write a key/value pair to the DHT. + dht:query Find the closest Peer IDs to a given Peer ID by querying the DHT. + diag + diag:cmds:clear Clear inactive requests from the log. + diag:cmds:set-time Set how long to keep inactive requests in the log. + diag:sys Print system diagnostic information. + file + file:ls List directory contents for Unix filesystem objects. + files + files:chcid Change the cid version or hash function of the root node of a given path. + files:cp Copy files into mfs. + files:flush Flush a given path’s data to disk. + files:ls List directories in the local mutable namespace. + files:mkdir Make directories. + files:mv Move files. + files:read Read a file in a given mfs. + files:rm Remove a file. + files:stat Display file status. + files:write Write to a mutable file in a given filesystem. + filestore + filestore:dups List blocks that are both in the filestore and standard block storage. + filestore:ls List objects in filestore. + filestore:verify Verify objects in filestore. + key + key:gen Create a new keypair. + key:list List all local keypairs. + key:rename Rename a keypair. + key:rm Remove a keypair. + log + log:level Change the logging level. + log:ls List the logging subsystems. + log:tail Read the event log. + name + name:publish Publish IPNS names. + name:pubsub:cancel Cancel a name subscription. + name:pubsub:state Query the state of IPNS pubsub. + name:pubsub:subs Show current name subscriptions. + name:resolve Resolve IPNS names. + object + object:data Output the raw bytes of an IPFS object. + object:diff Display the diff between two ipfs objects. + object:get Get and serialize the DAG node named by . + object:links Output the links pointed to by the specified object. + object:new Create a new object from an ipfs template. + object:patch:add-link Add a link to a given object. + object:patch:append-data Append data to the data segment of a dag node. + object:patch:rm-link Remove a link from an object. + object:patch:set-data Set the data field of an IPFS object. + object:put Store input as a DAG object, print its key. + object:stat Get stats for the DAG node named by . + p2p + p2p:listener:close Close active p2p listener. + p2p:listener:ls List active p2p listeners. + p2p:listener:open Forward p2p connections to a network multiaddr. + p2p:stream:close Close active p2p stream. + p2p:stream:dial Dial to a p2p listener. + p2p:stream:ls List active p2p streams. + pin + pin:add Pin objects to local storage. + pin:ls List objects pinned to local storage. + pin:rm Remove pinned objects from local storage. + pin:update Update a recursive pin. + pin:verify Verify that recursive pins are complete. + pubsub + pubsub:ls List subscribed topics by name. + pubsub:peers List peers we are currently pubsubbing with. + pubsub:pub Publish a message to a given pubsub topic. + pubsub:sub Subscribe to messages on a given topic. + refs + refs:local List all local references. + repo + repo:fsck Remove repo lockfiles. + repo:gc Perform a garbage collection sweep on the repo. + repo:stat Get stats for the currently used repo. + repo:verify Verify all blocks in repo are not corrupted. + repo:version Show the repo version. + stats + stats:bitswap Show some diagnostic information on the bitswap agent. + stats:bw Print ipfs bandwidth information. + stats:repo Get stats for the currently used repo. + swarm + swarm:addrs:listen List interface listening addresses. + swarm:addrs:local List local addresses. + swarm:connect Open connection to a given address. + swarm:disconnect Close connection to a given address. + swarm:filters:add Add an address filter. + swarm:filters:rm Remove an address filter. + swarm:peers List peers with open connections. + tar + tar:add Import a tar file into ipfs. + tar:cat Export a tar file from IPFS. +``` + +## Usage + +simply use the commandline interface + +``` +$ bin/php-ipfs +$ bin/php-ipfs add ./composer.lock --wrap-with-directory --driver=IPFS\\Driver\\Cli +$ bin/php-ipfs add ./composer.lock --wrap-with-directory + +``` + +## PHAR + +to build a `phar` file simply run + +> we assume you have https://box-project.github.io/box2/ installed! + +``` +$ composer build +``` + +## Tests + +this library is well covered with [phpspec](http://www.phpspec.net/) + +``` +$ composer test +``` + diff --git a/www/multitube/vendor/ipfs/php-client/_config.yml b/www/multitube/vendor/ipfs/php-client/_config.yml new file mode 100644 index 0000000..2f7efbe --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-minimal \ No newline at end of file diff --git a/www/multitube/vendor/ipfs/php-client/bin/php-ipfs b/www/multitube/vendor/ipfs/php-client/bin/php-ipfs new file mode 100755 index 0000000..a9b2e1d --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/bin/php-ipfs @@ -0,0 +1,20 @@ +#!/usr/bin/env php +register(new ServiceProvider()); + $container[Application::class]->run(); +} + +run(); diff --git a/www/multitube/vendor/ipfs/php-client/bin/rebuild b/www/multitube/vendor/ipfs/php-client/bin/rebuild new file mode 100755 index 0000000..74cf521 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/bin/rebuild @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +composer rebuild-api + +echo "MODIFIED FILES:" +git ls-files -m src/Api + +git diff src/Api +exit $(git ls-files -m src/Api | wc -l) + diff --git a/www/multitube/vendor/ipfs/php-client/box.json b/www/multitube/vendor/ipfs/php-client/box.json new file mode 100644 index 0000000..e8f4d80 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/box.json @@ -0,0 +1,33 @@ + +{ + "alias": "php-ipfs.phar", + "chmod": "0755", + "compactors": [ + "Herrera\\Box\\Compactor\\Php" + ], + "directories": [ + "src" + ], + "directories-bin": [ + "src/Api", + "src/Annotation" + ], + "extract": true, + "files": [ + "LICENSE" + ], + "finder": [ + { + "name": "*.php", + "exclude": [ + "tests", "Tests" + ], + "in": "vendor" + } + ], + "git-commit": "git-commit", + "git-version": "git-version", + "main": "bin/php-ipfs", + "output": "php-ipfs.phar", + "stub": true +} \ No newline at end of file diff --git a/www/multitube/vendor/ipfs/php-client/composer.json b/www/multitube/vendor/ipfs/php-client/composer.json new file mode 100644 index 0000000..e349d18 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/composer.json @@ -0,0 +1,58 @@ +{ + "name": "ipfs/php-client", + "description": "ipfs client library", + "keywords" : ["ipfs", "api"], + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Robert Schönthal", + "email": "robert.schoenthal@gmail.com" + } + ], + "require": { + "php": "^7.0", + "pimple/pimple": "^3.0", + "php-http/httplug": "^1.1", + "symfony/process": "^3.2", + "webmozart/assert": "^1.2", + "symfony/console": "^3.0", + "doctrine/annotations": "^1.3", + "mattketmo/camel": "^1.1", + "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/type-resolver": ">=0.1.7", + "rybakit/arguments-resolver": "^0.5.0", + "php-http/message": "^1.4", + "php-http/multipart-stream-builder": "^1.0", + "php-http/client-common": "^1.4", + "php-http/discovery": "^1.1", + "symfony/dom-crawler": "^3.0", + "symfony/css-selector": "^3.0", + "nikic/php-parser": "^3.0" + }, + + "require-dev" :{ + "symfony/var-dumper" : "^3.0", + "php-http/guzzle6-adapter": ">=1.1.1", + "phpspec/phpspec": ">=3.0" + }, + "autoload": { + "psr-4": { + "IPFS\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "spec\\IPFS\\": "tests/spec" + } + }, + + "scripts" : { + "test": "vendor/bin/phpspec run -f pretty --ansi -vv $@", + "coverage": "vendor/bin/phpspec run -f pretty --ansi -vv -c phpspec.yml.coverage $@", + "cs": "php-cs-fixer fix", + "cs-check": "php-cs-fixer fix --dry-run -vv --diff", + "rebuild-api" : "php bin/php-ipfs rebuild && composer cs", + "build" : "rm -rf vendor/* && composer require php-http/guzzle6-adapter && composer install -q --ansi -a -o --no-dev && box --ansi -v build && composer --ansi -q update && git checkout -- composer.json" + } +} diff --git a/www/multitube/vendor/ipfs/php-client/composer.lock b/www/multitube/vendor/ipfs/php-client/composer.lock new file mode 100644 index 0000000..260ab62 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/composer.lock @@ -0,0 +1,2665 @@ +{ + "_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#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "459dbb5fa5662830a90ed5de05d6824b", + "packages": [ + { + "name": "clue/stream-filter", + "version": "v1.4.0", + "source": { + "type": "git", + "url": "https://github.com/clue/php-stream-filter.git", + "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/php-stream-filter/zipball/d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", + "reference": "d80fdee9b3a7e0d16fc330a22f41f3ad0eeb09d0", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "^5.0 || ^4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Clue\\StreamFilter\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "description": "A simple and modern approach to stream filtering in PHP", + "homepage": "https://github.com/clue/php-stream-filter", + "keywords": [ + "bucket brigade", + "callback", + "filter", + "php_user_filter", + "stream", + "stream_filter_append", + "stream_filter_register" + ], + "time": "2017-08-18T09:54:01+00:00" + }, + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.3-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2018-04-22T15:46:56+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.5.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "9f83dded91781a01c63574e387eaa769be769115" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/9f83dded91781a01c63574e387eaa769be769115", + "reference": "9f83dded91781a01c63574e387eaa769be769115", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2018-12-04T20:46:45+00:00" + }, + { + "name": "mattketmo/camel", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/MattKetmo/camel.git", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MattKetmo/camel/zipball/2d7753c62787933f6761108acc76f95d8bfee191", + "reference": "2d7753c62787933f6761108acc76f95d8bfee191", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.6.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Camel": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matthieu Moquet", + "email": "matthieu@moquet.net" + } + ], + "description": "Tiny library to handle words case transformation", + "keywords": [ + "camelcase", + "case", + "lowercase", + "snakecase", + "transform" + ], + "time": "2015-05-13T13:51:08+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v3.1.5", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-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" + ], + "time": "2018-02-28T20:30:58+00:00" + }, + { + "name": "php-http/client-common", + "version": "1.8.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/client-common.git", + "reference": "efe327f4305813aa9025662259b78323d25b9948" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/client-common/zipball/efe327f4305813aa9025662259b78323d25b9948", + "reference": "efe327f4305813aa9025662259b78323d25b9948", + "shasum": "" + }, + "require": { + "php": "^5.4 || ^7.0", + "php-http/httplug": "^1.1", + "php-http/message": "^1.6", + "php-http/message-factory": "^1.0", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0" + }, + "require-dev": { + "guzzlehttp/psr7": "^1.4", + "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2" + }, + "suggest": { + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Common HTTP Client implementations and tools for HTTPlug", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "common", + "http", + "httplug" + ], + "time": "2018-12-14T22:12:45+00:00" + }, + { + "name": "php-http/discovery", + "version": "1.4.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/discovery.git", + "reference": "9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/discovery/zipball/9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33", + "reference": "9a6cb24de552bfe1aa9d7d1569e2d49c5b169a33", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^2.0.2", + "php-http/httplug": "^1.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^2.4", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories", + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "homepage": "http://php-http.org", + "keywords": [ + "adapter", + "client", + "discovery", + "factory", + "http", + "message", + "psr7" + ], + "time": "2018-02-06T10:55:24+00:00" + }, + { + "name": "php-http/guzzle6-adapter", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/guzzle6-adapter.git", + "reference": "e884cf6dae5235fffd2a07f761e0066b9ebef170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/guzzle6-adapter/zipball/e884cf6dae5235fffd2a07f761e0066b9ebef170", + "reference": "e884cf6dae5235fffd2a07f761e0066b9ebef170", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0", + "php": ">=5.5.0", + "php-http/httplug": "^1.0" + }, + "provide": { + "php-http/async-client-implementation": "1.0", + "php-http/client-implementation": "1.0" + }, + "require-dev": { + "ext-curl": "*", + "php-http/adapter-integration-tests": "^0.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Adapter\\Guzzle6\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "David de Boer", + "email": "david@ddeboer.nl" + } + ], + "description": "Guzzle 6 HTTP Adapter", + "homepage": "http://httplug.io", + "keywords": [ + "Guzzle", + "http" + ], + "time": "2016-01-26T20:39:00+00:00" + }, + { + "name": "php-http/httplug", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/httplug.git", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/httplug/zipball/1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "reference": "1c6381726c18579c4ca2ef1ec1498fdae8bdf018", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "php-http/promise": "^1.0", + "psr/http-message": "^1.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTPlug, the HTTP client abstraction for PHP", + "homepage": "http://httplug.io", + "keywords": [ + "client", + "http" + ], + "time": "2016-08-31T08:30:17+00:00" + }, + { + "name": "php-http/message", + "version": "1.7.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message.git", + "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message/zipball/b159ffe570dffd335e22ef0b91a946eacb182fa1", + "reference": "b159ffe570dffd335e22ef0b91a946eacb182fa1", + "shasum": "" + }, + "require": { + "clue/stream-filter": "^1.4", + "php": "^5.4 || ^7.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "akeneo/phpspec-skip-example-extension": "^1.0", + "coduo/phpspec-data-provider-extension": "^1.0", + "ext-zlib": "*", + "guzzlehttp/psr7": "^1.0", + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4", + "slim/slim": "^3.0", + "zendframework/zend-diactoros": "^1.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation", + "zendframework/zend-diactoros": "Used with Diactoros Factories" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "HTTP Message related tools", + "homepage": "http://php-http.org", + "keywords": [ + "http", + "message", + "psr-7" + ], + "time": "2018-11-01T09:32:41+00:00" + }, + { + "name": "php-http/message-factory", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-http/message-factory.git", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/message-factory/zipball/a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "reference": "a478cb11f66a6ac48d8954216cfed9aa06a501a1", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "description": "Factory interfaces for PSR-7 HTTP Message", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "stream", + "uri" + ], + "time": "2015-12-19T14:08:53+00:00" + }, + { + "name": "php-http/multipart-stream-builder", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/multipart-stream-builder.git", + "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/multipart-stream-builder/zipball/1fa3c623fc813a43b39494b2a1612174e36e0fb0", + "reference": "1fa3c623fc813a43b39494b2a1612174e36e0fb0", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "php-http/discovery": "^1.0", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "require-dev": { + "php-http/message": "^1.5", + "phpunit/phpunit": "^4.8 || ^5.4", + "zendframework/zend-diactoros": "^1.3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.3-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "description": "A builder class that help you create a multipart stream", + "homepage": "http://php-http.org", + "keywords": [ + "factory", + "http", + "message", + "multipart stream", + "stream" + ], + "time": "2017-05-21T17:45:25+00:00" + }, + { + "name": "php-http/promise", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-http/promise.git", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-http/promise/zipball/dc494cdc9d7160b9a09bd5573272195242ce7980", + "reference": "dc494cdc9d7160b9a09bd5573272195242ce7980", + "shasum": "" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "^1.0", + "phpspec/phpspec": "^2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + }, + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + } + ], + "description": "Promise used for asynchronous HTTP requests", + "homepage": "http://httplug.io", + "keywords": [ + "promise" + ], + "time": "2016-01-26T13:27:02+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "reference": "21bdeb5f65d7ebf9f43b1b25d404f87deab5bfb6", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + ], + "time": "2017-09-11T18:02:19+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/bf329f6c1aadea3299f08ee804682b7c45b326a2", + "reference": "bf329f6c1aadea3299f08ee804682b7c45b326a2", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "time": "2017-11-10T14:09:06+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "0.4.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/9c977708995954784726e25d0cd1dddf4e65b0f7", + "reference": "9c977708995954784726e25d0cd1dddf4e65b0f7", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^5.2||^4.8.24" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.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" + } + ], + "time": "2017-07-14T14:27:02+00:00" + }, + { + "name": "pimple/pimple", + "version": "v3.2.3", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", + "shasum": "" + }, + "require": { + "php": ">=5.3.0", + "psr/container": "^1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.2.x-dev" + } + }, + "autoload": { + "psr-0": { + "Pimple": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", + "keywords": [ + "container", + "dependency injection" + ], + "time": "2018-01-21T07:42:36+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://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" + ], + "time": "2017-02-14T16:28:37+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "psr/log", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "2.0.5", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "reference": "5601c8a83fbba7ef674a7369456d12f1e0d0eafa", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~3.7.0", + "satooshi/php-coveralls": ">=1.0" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2016-02-11T07:05:27+00:00" + }, + { + "name": "rybakit/arguments-resolver", + "version": "v0.5.1", + "source": { + "type": "git", + "url": "https://github.com/rybakit/arguments-resolver.git", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rybakit/arguments-resolver/zipball/5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "reference": "5cb9f193794b62e42c0c7cf5c77d9366a4a4a236", + "shasum": "" + }, + "require": { + "php": "^5.4|^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "ArgumentsResolver\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Eugene Leonovich", + "email": "gen.work@gmail.com" + } + ], + "description": "ArgumentsResolver allows you to determine the arguments to pass to a function or method.", + "homepage": "https://github.com/rybakit/arguments-resolver", + "keywords": [ + "arguments", + "callable", + "function", + "injection", + "invoke", + "method", + "parameters", + "reflection", + "resolver" + ], + "time": "2017-01-03T12:20:50+00:00" + }, + { + "name": "symfony/console", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb", + "reference": "8f80fc39bbc3b7c47ee54ba7aa2653521ace94bb", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "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": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T12:48:07+00:00" + }, + { + "name": "symfony/css-selector", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/css-selector.git", + "reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/345b9a48595d1ab9630db791dbc3e721bf0233e8", + "reference": "345b9a48595d1ab9630db791dbc3e721bf0233e8", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\CssSelector\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony CssSelector Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T19:48:54+00:00" + }, + { + "name": "symfony/debug", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/e0a2b92ee0b5b934f973d90c2f58e18af109d276", + "reference": "e0a2b92ee0b5b934f973d90c2f58e18af109d276", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "~3.4|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-11-28T18:24:18+00:00" + }, + { + "name": "symfony/dom-crawler", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "b6e94248eb4f8602a5825301b0bea1eb8cc82cfa" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b6e94248eb4f8602a5825301b0bea1eb8cc82cfa", + "reference": "b6e94248eb4f8602a5825301b0bea1eb8cc82cfa", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "symfony/css-selector": "~2.8|~3.0|~4.0" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "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": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2018-11-26T10:17:44+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba", + "reference": "a9c38e8a3da2c03b3e71fdffa6efb0bda51390ba", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "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": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2018-11-11T19:52:12+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.10.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494", + "reference": "c79c051f5b3a46be09205c73b80b346e4153e494", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.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": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-09-21T13:07:52+00:00" + }, + { + "name": "symfony/process", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2", + "reference": "abb46b909dd6ba0b50e10d4c10ffe6ee96dd70f2", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "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": "Symfony Process Component", + "homepage": "https://symfony.com", + "time": "2018-11-20T16:10:26+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/0df1908962e7a3071564e857d86874dad1ef204a", + "reference": "0df1908962e7a3071564e857d86874dad1ef204a", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.6", + "sebastian/version": "^1.0.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "time": "2018-01-29T19:49:41+00:00" + } + ], + "packages-dev": [ + { + "name": "doctrine/instantiator", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/instantiator.git", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "reference": "185b8868aa9bf7159f5f953ed5afb2d7fcdc3bda", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "athletic/athletic": "~0.1.8", + "ext-pdo": "*", + "ext-phar": "*", + "phpunit/phpunit": "^6.2.3", + "squizlabs/php_codesniffer": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "homepage": "http://ocramius.github.com/" + } + ], + "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", + "homepage": "https://github.com/doctrine/instantiator", + "keywords": [ + "constructor", + "instantiate" + ], + "time": "2017-07-22T11:58:36+00:00" + }, + { + "name": "phpspec/php-diff", + "version": "v1.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/php-diff.git", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/php-diff/zipball/0464787bfa7cd13576c5a1e318709768798bec6a", + "reference": "0464787bfa7cd13576c5a1e318709768798bec6a", + "shasum": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Diff": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Chris Boulton", + "homepage": "http://github.com/chrisboulton" + } + ], + "description": "A comprehensive library for generating differences between two hashable objects (strings or arrays).", + "time": "2016-04-07T12:29:16+00:00" + }, + { + "name": "phpspec/phpspec", + "version": "5.1.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/phpspec.git", + "reference": "4badea737c34a6c8e2921fca0f6a1cbe4f724f2f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/phpspec/zipball/4badea737c34a6c8e2921fca0f6a1cbe4f724f2f", + "reference": "4badea737c34a6c8e2921fca0f6a1cbe4f724f2f", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.5", + "ext-tokenizer": "*", + "php": "^7.1, <7.4", + "phpspec/php-diff": "^1.0.0", + "phpspec/prophecy": "^1.7", + "sebastian/exporter": "^1.0 || ^2.0 || ^3.0", + "symfony/console": "^3.4 || ^4.0", + "symfony/event-dispatcher": "^3.4 || ^4.0", + "symfony/finder": "^3.4 || ^4.0", + "symfony/process": "^3.4 || ^4.0", + "symfony/yaml": "^3.4 || ^4.0" + }, + "require-dev": { + "behat/behat": "^3.3", + "phpunit/phpunit": "^5.7 || ^6.0", + "symfony/filesystem": "^3.4 || ^4.0" + }, + "suggest": { + "phpspec/nyan-formatters": "Adds Nyan formatters" + }, + "bin": [ + "bin/phpspec" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.1.x-dev" + } + }, + "autoload": { + "psr-0": { + "PhpSpec": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "homepage": "http://marcelloduarte.net/" + }, + { + "name": "Ciaran McNulty", + "homepage": "https://ciaranmcnulty.com/" + } + ], + "description": "Specification-oriented BDD framework for PHP 5.6+", + "homepage": "http://phpspec.net/", + "keywords": [ + "BDD", + "SpecBDD", + "TDD", + "spec", + "specification", + "testing", + "tests" + ], + "time": "2018-10-29T08:12:52+00:00" + }, + { + "name": "phpspec/prophecy", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/phpspec/prophecy.git", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "reference": "4ba436b55987b4bf311cb7c6ba82aa528aac0a06", + "shasum": "" + }, + "require": { + "doctrine/instantiator": "^1.0.2", + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0", + "sebastian/comparator": "^1.1|^2.0|^3.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5|^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-0": { + "Prophecy\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" + }, + { + "name": "Marcello Duarte", + "email": "marcello.duarte@gmail.com" + } + ], + "description": "Highly opinionated mocking framework for PHP 5.3+", + "homepage": "https://github.com/phpspec/prophecy", + "keywords": [ + "Double", + "Dummy", + "fake", + "mock", + "spy", + "stub" + ], + "time": "2018-08-05T17:53:17+00:00" + }, + { + "name": "sebastian/comparator", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "shasum": "" + }, + "require": { + "php": "^7.1", + "sebastian/diff": "^3.0", + "sebastian/exporter": "^3.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.1" + }, + "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": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "time": "2018-07-12T15:12:46+00:00" + }, + { + "name": "sebastian/diff", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "366541b989927187c4ca70490a35615d3fef2dce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/366541b989927187c4ca70490a35615d3fef2dce", + "reference": "366541b989927187c4ca70490a35615d3fef2dce", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^7.0", + "symfony/process": "^2 || ^3.3 || ^4" + }, + "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": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "time": "2018-06-10T07:54:39+00:00" + }, + { + "name": "sebastian/exporter", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/234199f4528de6d12aaa58b612e98f7d36adb937", + "reference": "234199f4528de6d12aaa58b612e98f7d36adb937", + "shasum": "" + }, + "require": { + "php": "^7.0", + "sebastian/recursion-context": "^3.0" + }, + "require-dev": { + "ext-mbstring": "*", + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "http://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "time": "2017-04-03T13:19:02+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "reference": "5b0cd723502bac3b006cbf3dbf7a1e3fcefe4fa8", + "shasum": "" + }, + "require": { + "php": "^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^6.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "time": "2017-03-03T06:23:57+00:00" + }, + { + "name": "symfony/contracts", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/contracts.git", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/contracts/zipball/1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "reference": "1aa7ab2429c3d594dd70689604b5cf7421254cdf", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "require-dev": { + "psr/cache": "^1.0", + "psr/container": "^1.0" + }, + "suggest": { + "psr/cache": "When using the Cache contracts", + "psr/container": "When using the Service contracts", + "symfony/cache-contracts-implementation": "", + "symfony/service-contracts-implementation": "", + "symfony/translation-contracts-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\": "" + }, + "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": "A set of abstractions extracted out of the Symfony components", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2018-12-05T08:06:11+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/921f49c3158a276d27c0d770a5a347a3b718b328", + "reference": "921f49c3158a276d27c0d770a5a347a3b718b328", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/contracts": "^1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "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": "Symfony EventDispatcher Component", + "homepage": "https://symfony.com", + "time": "2018-12-01T08:52:38+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/e53d477d7b5c4982d0e1bfd2298dbee63d01441d", + "reference": "e53d477d7b5c4982d0e1bfd2298dbee63d01441d", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-dev" + } + }, + "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": "Symfony Finder Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T19:52:12+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v3.4.20", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "6867713afe6c50ade2f34ed6435563b065a52145" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6867713afe6c50ade2f34ed6435563b065a52145", + "reference": "6867713afe6c50ade2f34ed6435563b065a52145", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "require-dev": { + "ext-iconv": "*", + "twig/twig": "~1.34|~2.4" + }, + "suggest": { + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", + "ext-symfony_debug": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "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": "Symfony mechanism for exploring and dumping PHP variables", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "time": "2018-11-20T16:10:26+00:00" + }, + { + "name": "symfony/yaml", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "c41175c801e3edfda90f32e292619d10c27103d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c41175c801e3edfda90f32e292619d10c27103d7", + "reference": "c41175c801e3edfda90f32e292619d10c27103d7", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-ctype": "~1.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.2-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": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-11-11T19:52:12+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": "^7.0" + }, + "platform-dev": [] +} diff --git a/www/multitube/vendor/ipfs/php-client/phpspec.yml.coverage b/www/multitube/vendor/ipfs/php-client/phpspec.yml.coverage new file mode 100644 index 0000000..8281b9d --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/phpspec.yml.coverage @@ -0,0 +1,19 @@ +suites: + default: + namespace: IPFS + psr4_prefix: IPFS + spec_path: tests + +extensions: + PhpSpecCodeCoverage\CodeCoverageExtension: + whitelist: [src] + format: + - text + - clover + - html + + output: + clover: coverage.xml + html: coverage + +bootstrap: tests/spec/bootstrap.php diff --git a/www/multitube/vendor/ipfs/php-client/phpspec.yml.dist b/www/multitube/vendor/ipfs/php-client/phpspec.yml.dist new file mode 100644 index 0000000..d3051e1 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/phpspec.yml.dist @@ -0,0 +1,7 @@ +suites: + default: + namespace: IPFS + psr4_prefix: IPFS + spec_path: tests + +bootstrap: tests/spec/bootstrap.php \ No newline at end of file diff --git a/www/multitube/vendor/ipfs/php-client/src/Annotation/Api.php b/www/multitube/vendor/ipfs/php-client/src/Annotation/Api.php new file mode 100644 index 0000000..c7e5a52 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Annotation/Api.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Annotation; + +use Doctrine\Common\Annotations\Annotation; + +/** + * @Annotation() + * @Annotation\Target({"METHOD"}) + * @Annotation\Attributes({ + * @Annotation\Attribute("name", type="string", required=true) + * }) + */ +class Api +{ + public $name = null; +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Annotation/Param.php b/www/multitube/vendor/ipfs/php-client/src/Annotation/Param.php new file mode 100644 index 0000000..f6c5758 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Annotation/Param.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Annotation; + +class Param +{ + private $name; + + private $description; + + private $default; + + public function __construct(string $name, string $description, $default = __CLASS__) + { + $this->name = $name; + $this->description = $description; + $this->default = $default; + } + + public function getDefault() + { + return __CLASS__ === $this->default ? null : $this->default; + } + + public function getName(): string + { + return $this->name; + } + + public function getDescription(): string + { + return $this->description; + } + + public function hasDefault(): bool + { + return __CLASS__ !== $this->default; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Api.php b/www/multitube/vendor/ipfs/php-client/src/Api/Api.php new file mode 100644 index 0000000..4188fd2 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Api.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +interface Api +{ +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/ApiBuilder.php b/www/multitube/vendor/ipfs/php-client/src/Api/ApiBuilder.php new file mode 100644 index 0000000..7c0b012 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/ApiBuilder.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +class ApiBuilder +{ + /** + * @var ApiParser + */ + private $parser; + /** + * @var ApiGenerator + */ + private $generator; + + public function __construct(ApiParser $parser, ApiGenerator $generator) + { + $this->parser = $parser; + $this->generator = $generator; + } + + public function build($url = 'https://docs.ipfs.io/reference/api/http/', $prefix = '#api-v0') + { + //parse + $config = $this->parser->build($url, $prefix); + + //dump + $this->generator->build($config); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/ApiGenerator.php b/www/multitube/vendor/ipfs/php-client/src/Api/ApiGenerator.php new file mode 100644 index 0000000..cf73b22 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/ApiGenerator.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; +use IPFS\Utils\CaseFormatter; +use PhpParser\Builder\Method; +use PhpParser\BuilderFactory; +use PhpParser\Node; +use PhpParser\PrettyPrinter\Standard; + +class ApiGenerator +{ + /** + * @var BuilderFactory + */ + private $builder; + /** + * @var string + */ + private $location; + + public function __construct(BuilderFactory $builder, $location = __DIR__) + { + $this->builder = $builder; + $this->location = $location; + } + + public function build(array $configs) + { + foreach ($configs as $name => $config) { + $methods = []; + + foreach ($config as $methodConfig) { + $method = $this->buildMethodNode($methodConfig); + + $methods[] = $method; + } + + $header = $this->buildHeaderNode(); + $class = $this->buildClassNode($name, $methods); + + $prettyPrinter = new Standard(); + + file_put_contents( + $this->location . '/' . ucfirst(CaseFormatter::dashToCamel($this->generateClassName($name))) . '.php', + $prettyPrinter->prettyPrintFile([$header, $class]) + ); + } + } + + private function buildMethodNode(array $methodConfig): Method + { + $method = $this->builder + ->method($methodConfig['method']) + ->makePublic() + ->setReturnType('Command') + ->setDocComment($this->buildDocBlock($methodConfig)); + + foreach ($methodConfig['arguments'] as $parameterConfig) { + $parameter = $this->builder + ->param($parameterConfig['name']) + ->setTypeHint($parameterConfig['type']); + + if (!$parameterConfig['required']) { + $default = $parameterConfig['default']; + + if ('int' === $parameterConfig['type']) { + $default = (int) $default; + } + $parameter->setDefault($default); + } + + $method->addParam($parameter); + } + + $method->addStmt(new Node\Stmt\Return_( + new Node\Expr\New_(new Node\Name('Command'), [ + new Node\Scalar\MagicConst\Method(), + new Node\Expr\FuncCall(new Node\Name('get_defined_vars')), + ]) + )); + + return $method; + } + + private function buildClassNode(string $name, array $methods): Node + { + return $this->builder->namespace('IPFS\Api') + ->addStmt($this->builder->use(Endpoint::class)->as('Endpoint')) + ->addStmt($this->builder->use(Command::class)) + ->addStmt( + $this->builder->class($this->generateClassName($name)) + ->implement('Api') + ->addStmts($methods) + ->setDocComment( + <<<'EOS' +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +EOS + ) + ->makeFinal() + ) + ->getNode(); + } + + private function generateClassName(string $name): string + { + if ('Object' === $name) { + return 'Cobject'; + } + + return $name; + } + + private function buildDocBlock(array $methodConfig): string + { + $params = count($methodConfig['arguments']) ? '' : '*'; + + foreach ($methodConfig['arguments'] as $index => $argument) { + $suffix = $index + 1 === count($methodConfig['arguments']) ? "\n*" : "\n"; + $params .= sprintf('* @param %s $%s %s%s', $argument['type'], $argument['name'], $argument['description'], $suffix); + } + + return << + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use Http\Client\HttpAsyncClient; +use Http\Message\MessageFactory; +use IPFS\Utils\CaseFormatter; +use Psr\Http\Message\ResponseInterface; +use Symfony\Component\DomCrawler\Crawler; + +class ApiParser +{ + /** + * @var HttpAsyncClient + */ + private $client; + /** + * @var MessageFactory + */ + private $messageFactory; + /** + * @var Crawler + */ + private $crawler; + + public function __construct(HttpAsyncClient $client, MessageFactory $messageFactory, Crawler $crawler) + { + $this->client = $client; + $this->messageFactory = $messageFactory; + $this->crawler = $crawler; + } + + public function build(string $url = 'https://docs.ipfs.io/reference/api/http/', string $prefix = '#api-v0'): array + { + return $this->client + ->sendAsyncRequest($this->messageFactory->createRequest('GET', $url)) + ->then(function (ResponseInterface $response) use ($prefix) { + return $this->buildMethods($response, $prefix); + }) + ->wait() + ; + } + + private function buildMethods(ResponseInterface $response, $prefix): array + { + $this->crawler->addHtmlContent($response->getBody()->getContents()); + $links = $this->crawler->filter('main li a[href^="' . $prefix . '"]')->each(function (Crawler $node) { + return $node->attr('href'); + }); + + $config = []; + foreach ($links as $link) { + $link = $this->fixDocumentationLinks($link); + + $anchor = $this->crawler->filter($link)->first(); + $description = 'p' === $anchor->nextAll()->first()->getNode(0)->nodeName ? $anchor->nextAll()->first()->text() : null; + + $methodConfig = [ + 'parts' => str_replace('/', ':', str_replace('/api/v0/', '', $anchor->text())), + 'description' => $description, + 'arguments' => $this->parseArguments($anchor, $description ? 2 : 1), + ]; + + $nameParts = explode(':', $methodConfig['parts']); + if (count($nameParts) > 1) { + $class = array_shift($nameParts); + $methodConfig['class'] = ucfirst(CaseFormatter::dashToCamel($class)); + $methodConfig['method'] = CaseFormatter::dashToCamel(implode('-', $nameParts)); + } else { + $methodConfig['class'] = 'Basics'; + $methodConfig['method'] = CaseFormatter::dashToCamel($methodConfig['parts']); + } + + $config[$methodConfig['class']][] = $methodConfig; + } + + return $config; + } + + private function parseArguments(Crawler $anchor, int $index): array + { + $argumentsRootNode = $anchor->nextAll()->eq($index)->first(); + + if ('ul' === $argumentsRootNode->getNode(0)->nodeName) { + $names = []; + + return $argumentsRootNode->filter('li')->each(function (Crawler $argument) use (&$names) { + $description = $argument->filter('code')->first()->getNode(0)->nextSibling->textContent; + $name = CaseFormatter::dashToCamel($argument->filter('code')->first()->text()); + if (!isset($names[$name])) { + $names[$name] = 0; + } else { + ++$names[$name]; + } + + $config = [ + 'name' => 0 === $names[$name] ? $name : $name . $names[$name], + 'required' => $argument->filter('strong')->count() > 0, + 'description' => $this->parseDescription($description), + 'default' => $this->parseDefaultValue($description), + 'type' => $this->parseTypeHint($description), + ]; + + $config['default'] = 'bool' === $config['type'] && null === $config['default'] ? false : $config['default']; + + //fixup files + if ('file' === $config['type']) { + $config['type'] = 'string'; + $config['name'] = 'file'; + } + + return $config; + }); + } + + return []; + } + + private function parseDefaultValue(string $description) + { + preg_match('/Default.* [‘|"|“]([^\.]+)[’|"|”]\./', $description, $default); + + if (2 === count($default)) { + $default = preg_replace('/[^\x00-\x7f]/', '', $default[1]); + + return CaseFormatter::stringToBool($default); + } + } + + private function parseDescription($description): string + { + preg_match('/\]\: (.+)/', $description, $default); + + if (count($default) > 1) { + return substr($default[1], 0, strpos($default[1], '.') ?: strlen($default[1])) . '.'; + } + } + + private function parseTypeHint(string $description): string + { + preg_match('/\[([^\]]+)\]/', $description, $default); + + if (count($default) > 1) { + return $default[1]; + } + } + + private function fixDocumentationLinks(string $link): string + { + if ('#api-v0-statsrepo' === $link) { + return '#api-v0-stats-repo'; + } + + return $link; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Basics.php b/www/multitube/vendor/ipfs/php-client/src/Api/Basics.php new file mode 100644 index 0000000..4da8fdd --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Basics.php @@ -0,0 +1,237 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Basics implements Api +{ + /** + * Add a file or directory to ipfs. + * + * @Endpoint(name="add") + * + * @param string $file the path to a file to be added to ipfs + * @param bool $recursive add directory paths recursively + * @param bool $quiet write minimal output + * @param bool $quieter write only final hash + * @param bool $silent write no output + * @param bool $progress stream progress data + * @param bool $trickle use trickle-dag format for dag generation + * @param bool $onlyHash only chunk and hash - do not write to disk + * @param bool $wrapWithDirectory wrap files with a directory object + * @param bool $hidden include files that are hidden + * @param string $chunker chunking algorithm, size-[bytes] or rabin-[min]-[avg]-[max] + * @param bool $pin pin this object when adding + * @param bool $rawLeaves use raw blocks for leaf nodes + * @param bool $nocopy add the file using filestore + * @param bool $fscache check the filestore for pre-existing blocks + * @param int $cidVersion CID version + * @param string $hash hash function to use + * + * @return Command + */ + public function add(string $file, bool $recursive = false, bool $quiet = false, bool $quieter = false, bool $silent = false, bool $progress = false, bool $trickle = false, bool $onlyHash = false, bool $wrapWithDirectory = false, bool $hidden = false, string $chunker = 'size-262144', bool $pin = true, bool $rawLeaves = false, bool $nocopy = false, bool $fscache = false, int $cidVersion = 0, string $hash = 'sha2-256'): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show IPFS object data. + * + * @Endpoint(name="cat") + * + * @param string $arg the path to the IPFS object(s) to be outputted + * @param int $offset byte offset to begin reading from + * @param int $length maximum number of bytes to read + * + * @return Command + */ + public function cat(string $arg, int $offset = 0, int $length = 0): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List all available commands. + * + * @Endpoint(name="commands") + * + * @param bool $flags show command flags + * + * @return Command + */ + public function commands(bool $flags = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Resolve DNS links. + * + * @Endpoint(name="dns") + * + * @param string $arg the domain-name name to resolve + * @param bool $recursive resolve until the result is not a DNS link + * + * @return Command + */ + public function dns(string $arg, bool $recursive = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Download IPFS objects. + * + * @Endpoint(name="get") + * + * @param string $arg the path to the IPFS object(s) to be outputted + * @param string $output the path where the output should be stored + * @param bool $archive output a TAR archive + * @param bool $compress compress the output with GZIP compression + * @param int $compressionLevel the level of compression (1-9) + * + * @return Command + */ + public function get(string $arg, string $output = null, bool $archive = false, bool $compress = false, int $compressionLevel = 0): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show ipfs node id info. + * + * @Endpoint(name="id") + * + * @param string $arg peer + * @param string $format optional output format + * + * @return Command + */ + public function id(string $arg = null, string $format = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List directory contents for Unix filesystem objects. + * + * @Endpoint(name="ls") + * + * @param string $arg the path to the IPFS object(s) to list links from + * @param bool $headers print table headers (Hash, Size, Name) + * @param bool $resolveType resolve linked objects to find out their types + * + * @return Command + */ + public function ls(string $arg, bool $headers = false, bool $resolveType = true): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Mounts IPFS to the filesystem (read-only). + * + * @Endpoint(name="mount") + * + * @param string $ipfsPath the path where IPFS should be mounted + * @param string $ipnsPath the path where IPNS should be mounted + * + * @return Command + */ + public function mount(string $ipfsPath = null, string $ipnsPath = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Send echo request packets to IPFS hosts. + * + * @Endpoint(name="ping") + * + * @param string $arg ID of peer to be pinged + * @param int $count number of ping messages to send + * + * @return Command + */ + public function ping(string $arg, int $count = 10): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Resolve the value of names to IPFS. + * + * @Endpoint(name="resolve") + * + * @param string $arg the name to resolve + * @param bool $recursive resolve until the result is an IPFS name + * @param uint $dhtRecordCount number of records to request for DHT resolution + * @param string $dhtTimeout max time to collect values during DHT resolution eg “30s” + * + * @return Command + */ + public function resolve(string $arg, bool $recursive = false, uint $dhtRecordCount = null, string $dhtTimeout = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Shut down the ipfs daemon. + * + * @Endpoint(name="shutdown") + * + * @return Command + */ + public function shutdown(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * @Endpoint(name="update") + * + * @param string $arg arguments for subcommand + * + * @return Command + */ + public function update(string $arg = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show ipfs version information. + * + * @Endpoint(name="version") + * + * @param bool $number only show the version number + * @param bool $commit show the commit hash + * @param bool $repo show repo version + * @param bool $all show all version information + * + * @return Command + */ + public function version(bool $number = false, bool $commit = false, bool $repo = false, bool $all = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Bitswap.php b/www/multitube/vendor/ipfs/php-client/src/Api/Bitswap.php new file mode 100644 index 0000000..07ba41f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Bitswap.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Bitswap implements Api +{ + /** + * Show the current ledger for a peer. + * + * @Endpoint(name="bitswap:ledger") + * + * @param string $arg the PeerID (B58) of the ledger to inspect + * + * @return Command + */ + public function ledger(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Trigger reprovider. + * + * @Endpoint(name="bitswap:reprovide") + * + * @return Command + */ + public function reprovide(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show some diagnostic information on the bitswap agent. + * + * @Endpoint(name="bitswap:stat") + * + * @return Command + */ + public function stat(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove a given block from your wantlist. + * + * @Endpoint(name="bitswap:unwant") + * + * @param string $arg key(s) to remove from your wantlist + * + * @return Command + */ + public function unwant(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show blocks currently on the wantlist. + * + * @Endpoint(name="bitswap:wantlist") + * + * @param string $peer specify which peer to show wantlist for + * + * @return Command + */ + public function wantlist(string $peer = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Block.php b/www/multitube/vendor/ipfs/php-client/src/Api/Block.php new file mode 100644 index 0000000..c7d7e2c --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Block.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Block implements Api +{ + /** + * Get a raw IPFS block. + * + * @Endpoint(name="block:get") + * + * @param string $arg the base58 multihash of an existing block to get + * + * @return Command + */ + public function get(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Store input as an IPFS block. + * + * @Endpoint(name="block:put") + * + * @param string $file the data to be stored as an IPFS block + * @param string $format cid format for blocks to be created with + * @param string $mhtype multihash hash function + * @param int $mhlen multihash hash length + * + * @return Command + */ + public function put(string $file, string $format = null, string $mhtype = 'sha2-256', int $mhlen = -1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove IPFS block(s). + * + * @Endpoint(name="block:rm") + * + * @param string $arg bash58 encoded multihash of block(s) to remove + * @param bool $force ignore nonexistent blocks + * @param bool $quiet write minimal output + * + * @return Command + */ + public function rm(string $arg, bool $force = false, bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Print information of a raw IPFS block. + * + * @Endpoint(name="block:stat") + * + * @param string $arg the base58 multihash of an existing block to stat + * + * @return Command + */ + public function stat(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Bootstrap.php b/www/multitube/vendor/ipfs/php-client/src/Api/Bootstrap.php new file mode 100644 index 0000000..eca99c9 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Bootstrap.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Bootstrap implements Api +{ + /** + * Add default peers to the bootstrap list. + * + * @Endpoint(name="bootstrap:add:default") + * + * @return Command + */ + public function addDefault(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show peers in the bootstrap list. + * + * @Endpoint(name="bootstrap:list") + * + * @return Command + */ + public function list(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove all peers from the bootstrap list. + * + * @Endpoint(name="bootstrap:rm:all") + * + * @return Command + */ + public function rmAll(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Cobject.php b/www/multitube/vendor/ipfs/php-client/src/Api/Cobject.php new file mode 100644 index 0000000..0abb6ed --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Cobject.php @@ -0,0 +1,192 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Cobject implements Api +{ + /** + * Output the raw bytes of an IPFS object. + * + * @Endpoint(name="object:data") + * + * @param string $arg key of the object to retrieve, in base58-encoded multihash format + * + * @return Command + */ + public function data(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Display the diff between two ipfs objects. + * + * @Endpoint(name="object:diff") + * + * @param string $arg object to diff against + * @param string $arg1 object to diff + * @param bool $verbose print extra information + * + * @return Command + */ + public function diff(string $arg, string $arg1, bool $verbose = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Get and serialize the DAG node named by . + * + * @Endpoint(name="object:get") + * + * @param string $arg key of the object to retrieve, in base58-encoded multihash format + * + * @return Command + */ + public function get(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Output the links pointed to by the specified object. + * + * @Endpoint(name="object:links") + * + * @param string $arg key of the object to retrieve, in base58-encoded multihash format + * @param bool $headers print table headers (Hash, Size, Name) + * + * @return Command + */ + public function links(string $arg, bool $headers = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Create a new object from an ipfs template. + * + * @Endpoint(name="object:new") + * + * @param string $arg template to use + * + * @return Command + */ + public function new(string $arg = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Add a link to a given object. + * + * @Endpoint(name="object:patch:add-link") + * + * @param string $arg the hash of the node to modify + * @param string $arg1 name of link to create + * @param string $arg2 IPFS object to add link to + * @param bool $create create intermediary nodes + * + * @return Command + */ + public function patchAddLink(string $arg, string $arg1, string $arg2, bool $create = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Append data to the data segment of a dag node. + * + * @Endpoint(name="object:patch:append-data") + * + * @param string $arg the hash of the node to modify + * @param string $file data to append + * + * @return Command + */ + public function patchAppendData(string $arg, string $file): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove a link from an object. + * + * @Endpoint(name="object:patch:rm-link") + * + * @param string $arg the hash of the node to modify + * @param string $arg1 name of the link to remove + * + * @return Command + */ + public function patchRmLink(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Set the data field of an IPFS object. + * + * @Endpoint(name="object:patch:set-data") + * + * @param string $arg the hash of the node to modify + * @param string $file the data to set the object to + * + * @return Command + */ + public function patchSetData(string $arg, string $file): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Store input as a DAG object, print its key. + * + * @Endpoint(name="object:put") + * + * @param string $file data to be stored as a DAG object + * @param string $inputenc encoding type of input data + * @param string $datafieldenc encoding type of the data field, either “text” or “base64” + * @param bool $pin pin this object when adding + * @param bool $quiet write minimal output + * + * @return Command + */ + public function put(string $file, string $inputenc = 'json', string $datafieldenc = 'text', bool $pin = false, bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Get stats for the DAG node named by . + * + * @Endpoint(name="object:stat") + * + * @param string $arg key of the object to retrieve, in base58-encoded multihash format + * + * @return Command + */ + public function stat(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Config.php b/www/multitube/vendor/ipfs/php-client/src/Api/Config.php new file mode 100644 index 0000000..8761974 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Config.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Config implements Api +{ + /** + * Open the config file for editing in $EDITOR. + * + * @Endpoint(name="config:edit") + * + * @return Command + */ + public function edit(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Apply profile to config. + * + * @Endpoint(name="config:profile:apply") + * + * @param string $arg the profile to apply to the config + * + * @return Command + */ + public function profileApply(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Replace the config with . + * + * @Endpoint(name="config:replace") + * + * @param string $file the file to use as the new config + * + * @return Command + */ + public function replace(string $file): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Output config file contents. + * + * @Endpoint(name="config:show") + * + * @return Command + */ + public function show(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Dag.php b/www/multitube/vendor/ipfs/php-client/src/Api/Dag.php new file mode 100644 index 0000000..b451899 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Dag.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Dag implements Api +{ + /** + * Get a dag node from ipfs. + * + * @Endpoint(name="dag:get") + * + * @param string $arg the object to get Required: + * + * @return Command + */ + public function get(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Add a dag node to ipfs. + * + * @Endpoint(name="dag:put") + * + * @param string $file the object to put Required: + * @param string $format format that the object will be added as + * @param string $inputEnc format that the input object will be + * @param bool $pin pin this object when adding + * @param string $hash hash function to use + * + * @return Command + */ + public function put(string $file, string $format = 'cbor', string $inputEnc = 'json', bool $pin = false, string $hash = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Resolve ipld block. + * + * @Endpoint(name="dag:resolve") + * + * @param string $arg the path to resolve Required: + * + * @return Command + */ + public function resolve(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Dht.php b/www/multitube/vendor/ipfs/php-client/src/Api/Dht.php new file mode 100644 index 0000000..7784935 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Dht.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Dht implements Api +{ + /** + * Query the DHT for all of the multiaddresses associated with a Peer ID. + * + * @Endpoint(name="dht:findpeer") + * + * @param string $arg the ID of the peer to search for + * @param bool $verbose print extra information + * + * @return Command + */ + public function findpeer(string $arg, bool $verbose = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Find peers in the DHT that can provide a specific value, given a key. + * + * @Endpoint(name="dht:findprovs") + * + * @param string $arg the key to find providers for + * @param bool $verbose print extra information + * @param int $numProviders the number of providers to find + * + * @return Command + */ + public function findprovs(string $arg, bool $verbose = false, int $numProviders = 20): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Given a key, query the DHT for its best value. + * + * @Endpoint(name="dht:get") + * + * @param string $arg the key to find a value for + * @param bool $verbose print extra information + * + * @return Command + */ + public function get(string $arg, bool $verbose = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Announce to the network that you are providing given values. + * + * @Endpoint(name="dht:provide") + * + * @param string $arg the key[s] to send provide records for + * @param bool $verbose print extra information + * @param bool $recursive recursively provide entire graph + * + * @return Command + */ + public function provide(string $arg, bool $verbose = false, bool $recursive = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Write a key/value pair to the DHT. + * + * @Endpoint(name="dht:put") + * + * @param string $arg the key to store the value at + * @param string $arg1 the value to store + * @param bool $verbose print extra information + * + * @return Command + */ + public function put(string $arg, string $arg1, bool $verbose = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Find the closest Peer IDs to a given Peer ID by querying the DHT. + * + * @Endpoint(name="dht:query") + * + * @param string $arg the peerID to run the query against + * @param bool $verbose print extra information + * + * @return Command + */ + public function query(string $arg, bool $verbose = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Diag.php b/www/multitube/vendor/ipfs/php-client/src/Api/Diag.php new file mode 100644 index 0000000..7c0f657 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Diag.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Diag implements Api +{ + /** + * Clear inactive requests from the log. + * + * @Endpoint(name="diag:cmds:clear") + * + * @return Command + */ + public function cmdsClear(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Set how long to keep inactive requests in the log. + * + * @Endpoint(name="diag:cmds:set-time") + * + * @param string $arg time to keep inactive requests in log + * + * @return Command + */ + public function cmdsSetTime(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Print system diagnostic information. + * + * @Endpoint(name="diag:sys") + * + * @return Command + */ + public function sys(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/File.php b/www/multitube/vendor/ipfs/php-client/src/Api/File.php new file mode 100644 index 0000000..147d1dc --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/File.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class File implements Api +{ + /** + * List directory contents for Unix filesystem objects. + * + * @Endpoint(name="file:ls") + * + * @param string $arg the path to the IPFS object(s) to list links from + * + * @return Command + */ + public function ls(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Files.php b/www/multitube/vendor/ipfs/php-client/src/Api/Files.php new file mode 100644 index 0000000..d22921c --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Files.php @@ -0,0 +1,188 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Files implements Api +{ + /** + * Change the cid version or hash function of the root node of a given path. + * + * @Endpoint(name="files:chcid") + * + * @param string $arg path to change + * @param int $cidVersion cid version to use + * @param string $hash hash function to use + * + * @return Command + */ + public function chcid(string $arg = '/', int $cidVersion = 0, string $hash = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Copy files into mfs. + * + * @Endpoint(name="files:cp") + * + * @param string $arg source object to copy + * @param string $arg1 destination to copy object to + * + * @return Command + */ + public function cp(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Flush a given path’s data to disk. + * + * @Endpoint(name="files:flush") + * + * @param string $arg path to flush + * + * @return Command + */ + public function flush(string $arg = '/'): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List directories in the local mutable namespace. + * + * @Endpoint(name="files:ls") + * + * @param string $arg path to show listing for + * @param bool $l use long listing format + * + * @return Command + */ + public function ls(string $arg = '/', bool $l = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Make directories. + * + * @Endpoint(name="files:mkdir") + * + * @param string $arg path to dir to make + * @param bool $parents no error if existing, make parent directories as needed + * @param int $cidVersion cid version to use + * @param string $hash hash function to use + * + * @return Command + */ + public function mkdir(string $arg, bool $parents = false, int $cidVersion = 0, string $hash = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Move files. + * + * @Endpoint(name="files:mv") + * + * @param string $arg source file to move + * @param string $arg1 destination path for file to be moved to + * + * @return Command + */ + public function mv(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Read a file in a given mfs. + * + * @Endpoint(name="files:read") + * + * @param string $arg path to file to be read + * @param int $offset byte offset to begin reading from + * @param int $count maximum number of bytes to read + * + * @return Command + */ + public function read(string $arg, int $offset = 0, int $count = 0): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove a file. + * + * @Endpoint(name="files:rm") + * + * @param string $arg file to remove + * @param bool $recursive recursively remove directories + * + * @return Command + */ + public function rm(string $arg, bool $recursive = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Display file status. + * + * @Endpoint(name="files:stat") + * + * @param string $arg path to node to stat + * @param string $format print statistics in given format + * @param bool $hash print only hash + * @param bool $size print only size + * @param bool $withLocal compute the amount of the dag that is local, and if possible the total size + * + * @return Command + */ + public function stat(string $arg, string $format = null, bool $hash = false, bool $size = false, bool $withLocal = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Write to a mutable file in a given filesystem. + * + * @Endpoint(name="files:write") + * + * @param string $arg path to write to + * @param string $file data to write + * @param int $offset byte offset to begin writing at + * @param bool $create create the file if it does not exist + * @param bool $truncate truncate the file to size zero before writing + * @param int $count maximum number of bytes to read + * @param bool $rawLeaves use raw blocks for newly created leaf nodes + * @param int $cidVersion cid version to use + * @param string $hash hash function to use + * + * @return Command + */ + public function write(string $arg, string $file, int $offset = 0, bool $create = false, bool $truncate = false, int $count = 0, bool $rawLeaves = false, int $cidVersion = 0, string $hash = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Filestore.php b/www/multitube/vendor/ipfs/php-client/src/Api/Filestore.php new file mode 100644 index 0000000..6434839 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Filestore.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Filestore implements Api +{ + /** + * List blocks that are both in the filestore and standard block storage. + * + * @Endpoint(name="filestore:dups") + * + * @return Command + */ + public function dups(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List objects in filestore. + * + * @Endpoint(name="filestore:ls") + * + * @param string $arg cid of objects to list + * @param bool $fileOrder sort the results based on the path of the backing file + * + * @return Command + */ + public function ls(string $arg = null, bool $fileOrder = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Verify objects in filestore. + * + * @Endpoint(name="filestore:verify") + * + * @param string $arg cid of objects to verify + * @param bool $fileOrder verify the objects based on the order of the backing file + * + * @return Command + */ + public function verify(string $arg = null, bool $fileOrder = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Key.php b/www/multitube/vendor/ipfs/php-client/src/Api/Key.php new file mode 100644 index 0000000..f5dc4a8 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Key.php @@ -0,0 +1,86 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Key implements Api +{ + /** + * Create a new keypair. + * + * @Endpoint(name="key:gen") + * + * @param string $arg name of key to create Required: + * @param string $type type of the key to create [rsa, ed25519] + * @param int $size size of the key to generate + * + * @return Command + */ + public function gen(string $arg, string $type = null, int $size = 0): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List all local keypairs. + * + * @Endpoint(name="key:list") + * + * @param bool $l show extra information about keys + * + * @return Command + */ + public function list(bool $l = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Rename a keypair. + * + * @Endpoint(name="key:rename") + * + * @param string $arg name of key to rename Required: + * @param string $arg1 new name of the key Required: + * @param bool $force allow to overwrite an existing key + * + * @return Command + */ + public function rename(string $arg, string $arg1, bool $force = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove a keypair. + * + * @Endpoint(name="key:rm") + * + * @param string $arg names of keys to remove Required: + * @param bool $l show extra information about keys + * + * @return Command + */ + public function rm(string $arg, bool $l = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Log.php b/www/multitube/vendor/ipfs/php-client/src/Api/Log.php new file mode 100644 index 0000000..59ddcc7 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Log.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Log implements Api +{ + /** + * Change the logging level. + * + * @Endpoint(name="log:level") + * + * @param string $arg the subsystem logging identifier + * @param string $arg1 the log level, with ‘debug’ the most verbose and ‘critical’ the least verbose + * + * @return Command + */ + public function level(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List the logging subsystems. + * + * @Endpoint(name="log:ls") + * + * @return Command + */ + public function ls(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Read the event log. + * + * @Endpoint(name="log:tail") + * + * @return Command + */ + public function tail(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Name.php b/www/multitube/vendor/ipfs/php-client/src/Api/Name.php new file mode 100644 index 0000000..bfbd5af --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Name.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Name implements Api +{ + /** + * Publish IPNS names. + * + * @Endpoint(name="name:publish") + * + * @param string $arg ipfs path of the object to be published + * @param bool $resolve resolve given path before publishing + * @param string $lifetime time duration that the record will be valid for + * @param string $ttl time duration this record should be cached for (caution: experimental) + * @param string $key name of the key to be used or a valid PeerID, as listed by ‘ipfs key list -l’ + * + * @return Command + */ + public function publish(string $arg, bool $resolve = true, string $lifetime = '24h', string $ttl = null, string $key = 'self'): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Cancel a name subscription. + * + * @Endpoint(name="name:pubsub:cancel") + * + * @param string $arg name to cancel the subscription for + * + * @return Command + */ + public function pubsubCancel(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Query the state of IPNS pubsub. + * + * @Endpoint(name="name:pubsub:state") + * + * @return Command + */ + public function pubsubState(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show current name subscriptions. + * + * @Endpoint(name="name:pubsub:subs") + * + * @return Command + */ + public function pubsubSubs(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Resolve IPNS names. + * + * @Endpoint(name="name:resolve") + * + * @param string $arg the IPNS name to resolve + * @param bool $recursive resolve until the result is not an IPNS name + * @param bool $nocache do not use cached entries + * @param uint $dhtRecordCount number of records to request for DHT resolution + * @param string $dhtTimeout max time to collect values during DHT resolution eg “30s” + * + * @return Command + */ + public function resolve(string $arg = null, bool $recursive = false, bool $nocache = false, uint $dhtRecordCount = null, string $dhtTimeout = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/P2p.php b/www/multitube/vendor/ipfs/php-client/src/Api/P2p.php new file mode 100644 index 0000000..510ed7f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/P2p.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class P2p implements Api +{ + /** + * Close active p2p listener. + * + * @Endpoint(name="p2p:listener:close") + * + * @param string $arg P2P listener protocol Required: no + * @param bool $all close all listeners + * + * @return Command + */ + public function listenerClose(string $arg = null, bool $all = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List active p2p listeners. + * + * @Endpoint(name="p2p:listener:ls") + * + * @param bool $headers print table headers (HandlerID, Protocol, Local, Remote) + * + * @return Command + */ + public function listenerLs(bool $headers = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Forward p2p connections to a network multiaddr. + * + * @Endpoint(name="p2p:listener:open") + * + * @param string $arg protocol identifier + * @param string $arg1 request handling application address + * + * @return Command + */ + public function listenerOpen(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Close active p2p stream. + * + * @Endpoint(name="p2p:stream:close") + * + * @param string $arg stream HandlerID Required: no + * @param bool $all close all streams + * + * @return Command + */ + public function streamClose(string $arg = null, bool $all = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Dial to a p2p listener. + * + * @Endpoint(name="p2p:stream:dial") + * + * @param string $arg remote peer to connect to Required: + * @param string $arg1 protocol identifier + * @param string $arg2 address to listen for connection/s (default: /ip4/127 + * + * @return Command + */ + public function streamDial(string $arg, string $arg1, string $arg2 = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List active p2p streams. + * + * @Endpoint(name="p2p:stream:ls") + * + * @param bool $headers print table headers (HagndlerID, Protocol, Local, Remote) + * + * @return Command + */ + public function streamLs(bool $headers = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Pin.php b/www/multitube/vendor/ipfs/php-client/src/Api/Pin.php new file mode 100644 index 0000000..865fae6 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Pin.php @@ -0,0 +1,103 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Pin implements Api +{ + /** + * Pin objects to local storage. + * + * @Endpoint(name="pin:add") + * + * @param string $arg path to object(s) to be pinned + * @param bool $recursive recursively pin the object linked to by the specified object(s) + * @param bool $progress show progress + * + * @return Command + */ + public function add(string $arg, bool $recursive = true, bool $progress = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List objects pinned to local storage. + * + * @Endpoint(name="pin:ls") + * + * @param string $arg path to object(s) to be listed + * @param string $type the type of pinned keys to list + * @param bool $quiet write just hashes of objects + * + * @return Command + */ + public function ls(string $arg = null, string $type = 'all', bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove pinned objects from local storage. + * + * @Endpoint(name="pin:rm") + * + * @param string $arg path to object(s) to be unpinned + * @param bool $recursive recursively unpin the object linked to by the specified object(s) + * + * @return Command + */ + public function rm(string $arg, bool $recursive = true): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Update a recursive pin. + * + * @Endpoint(name="pin:update") + * + * @param string $arg path to old object + * @param string $arg1 path to new object to be pinned + * @param bool $unpin remove the old pin + * + * @return Command + */ + public function update(string $arg, string $arg1, bool $unpin = true): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Verify that recursive pins are complete. + * + * @Endpoint(name="pin:verify") + * + * @param bool $verbose also write the hashes of non-broken pins + * @param bool $quiet write just hashes of broken pins + * + * @return Command + */ + public function verify(bool $verbose = false, bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Pubsub.php b/www/multitube/vendor/ipfs/php-client/src/Api/Pubsub.php new file mode 100644 index 0000000..29ead49 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Pubsub.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Pubsub implements Api +{ + /** + * List subscribed topics by name. + * + * @Endpoint(name="pubsub:ls") + * + * @return Command + */ + public function ls(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List peers we are currently pubsubbing with. + * + * @Endpoint(name="pubsub:peers") + * + * @param string $arg topic to list connected peers of Required: no + * + * @return Command + */ + public function peers(string $arg = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Publish a message to a given pubsub topic. + * + * @Endpoint(name="pubsub:pub") + * + * @param string $arg topic to publish to + * @param string $arg1 payload of message to publish + * + * @return Command + */ + public function pub(string $arg, string $arg1): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Subscribe to messages on a given topic. + * + * @Endpoint(name="pubsub:sub") + * + * @param string $arg string name of topic to subscribe to + * @param bool $discover try to discover other peers subscribed to the same topic + * + * @return Command + */ + public function sub(string $arg, bool $discover = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Refs.php b/www/multitube/vendor/ipfs/php-client/src/Api/Refs.php new file mode 100644 index 0000000..525606e --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Refs.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Refs implements Api +{ + /** + * List all local references. + * + * @Endpoint(name="refs:local") + * + * @return Command + */ + public function local(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Repo.php b/www/multitube/vendor/ipfs/php-client/src/Api/Repo.php new file mode 100644 index 0000000..105c8b3 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Repo.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Repo implements Api +{ + /** + * Remove repo lockfiles. + * + * @Endpoint(name="repo:fsck") + * + * @return Command + */ + public function fsck(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Perform a garbage collection sweep on the repo. + * + * @Endpoint(name="repo:gc") + * + * @param bool $streamErrors stream errors + * @param bool $quiet write minimal output + * + * @return Command + */ + public function gc(bool $streamErrors = false, bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Get stats for the currently used repo. + * + * @Endpoint(name="repo:stat") + * + * @param bool $human output RepoSize in MiB + * + * @return Command + */ + public function stat(bool $human = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Verify all blocks in repo are not corrupted. + * + * @Endpoint(name="repo:verify") + * + * @return Command + */ + public function verify(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Show the repo version. + * + * @Endpoint(name="repo:version") + * + * @param bool $quiet write minimal output + * + * @return Command + */ + public function version(bool $quiet = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Stats.php b/www/multitube/vendor/ipfs/php-client/src/Api/Stats.php new file mode 100644 index 0000000..60440f5 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Stats.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Stats implements Api +{ + /** + * Show some diagnostic information on the bitswap agent. + * + * @Endpoint(name="stats:bitswap") + * + * @return Command + */ + public function bitswap(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Print ipfs bandwidth information. + * + * @Endpoint(name="stats:bw") + * + * @param string $peer specify a peer to print bandwidth for + * @param string $proto specify a protocol to print bandwidth for + * @param bool $poll print bandwidth at an interval + * @param string $interval time interval to wait between updating output, if ‘poll’ is true + * + * @return Command + */ + public function bw(string $peer = null, string $proto = null, bool $poll = false, string $interval = null): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Get stats for the currently used repo. + * + * @Endpoint(name="stats:repo") + * + * @param bool $human output RepoSize in MiB + * + * @return Command + */ + public function repo(bool $human = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Swarm.php b/www/multitube/vendor/ipfs/php-client/src/Api/Swarm.php new file mode 100644 index 0000000..ff11899 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Swarm.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Swarm implements Api +{ + /** + * List interface listening addresses. + * + * @Endpoint(name="swarm:addrs:listen") + * + * @return Command + */ + public function addrsListen(): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List local addresses. + * + * @Endpoint(name="swarm:addrs:local") + * + * @param bool $id show peer ID in addresses + * + * @return Command + */ + public function addrsLocal(bool $id = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Open connection to a given address. + * + * @Endpoint(name="swarm:connect") + * + * @param string $arg address of peer to connect to + * + * @return Command + */ + public function connect(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Close connection to a given address. + * + * @Endpoint(name="swarm:disconnect") + * + * @param string $arg address of peer to disconnect from + * + * @return Command + */ + public function disconnect(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Add an address filter. + * + * @Endpoint(name="swarm:filters:add") + * + * @param string $arg multiaddr to filter + * + * @return Command + */ + public function filtersAdd(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Remove an address filter. + * + * @Endpoint(name="swarm:filters:rm") + * + * @param string $arg multiaddr filter to remove + * + * @return Command + */ + public function filtersRm(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * List peers with open connections. + * + * @Endpoint(name="swarm:peers") + * + * @param bool $verbose display all extra information + * @param bool $streams also list information about open streams for each peer + * @param bool $latency also list information about latency to each peer + * + * @return Command + */ + public function peers(bool $verbose = false, bool $streams = false, bool $latency = false): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Api/Tar.php b/www/multitube/vendor/ipfs/php-client/src/Api/Tar.php new file mode 100644 index 0000000..d544827 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Api/Tar.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Api; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Command\Command; + +/** + * @author Robert Schönthal + * @autogenerated + * @codeCoverageIgnore + */ +final class Tar implements Api +{ + /** + * Import a tar file into ipfs. + * + * @Endpoint(name="tar:add") + * + * @param string $file tar file to add + * + * @return Command + */ + public function add(string $file): Command + { + return new Command(__METHOD__, get_defined_vars()); + } + + /** + * Export a tar file from IPFS. + * + * @Endpoint(name="tar:cat") + * + * @param string $arg ipfs path of archive to export + * + * @return Command + */ + public function cat(string $arg): Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Client.php b/www/multitube/vendor/ipfs/php-client/src/Client.php new file mode 100644 index 0000000..3b3737d --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Client.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS; + +use IPFS\Command\Command; +use IPFS\Driver\Driver; + +class Client implements Driver +{ + /** + * @var Driver + */ + private $driver; + + public function __construct(Driver $driver) + { + $this->driver = $driver; + } + + public function execute(Command $command) + { + return $this->driver->execute($command); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Command/Command.php b/www/multitube/vendor/ipfs/php-client/src/Command/Command.php new file mode 100644 index 0000000..812b76a --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Command/Command.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Command; + +use IPFS\Utils\CaseFormatter; + +class Command +{ + /** + * @var array + */ + private $args = []; + /** + * @var string + */ + private $method; + + public function __construct(string $method, array $args = []) + { + $this->args = $args; + $this->method = $method; + } + + public function getAction(): string + { + $parts = explode('\\', $this->method); + $shortName = array_pop($parts); + + $name = CaseFormatter::camelToColon(str_replace('::', ':', $shortName)); + + // correct some naming workaround due to reserved keywords + $name = str_replace('basics:', '', $name); + $name = str_replace('cobject:', 'object:', $name); + + return $name; + } + + public function getArguments(): array + { + return $this->args; + } + + public function getMethod(): string + { + return $this->method; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Console/ApiBuildCommand.php b/www/multitube/vendor/ipfs/php-client/src/Console/ApiBuildCommand.php new file mode 100644 index 0000000..1aa994f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Console/ApiBuildCommand.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ApiBuildCommand extends Command +{ + /** + * @var \Closure + */ + private $builder; + + public function __construct(\Closure $builder) + { + parent::__construct(null); + $this->builder = $builder; + } + + protected function configure() + { + $this + ->setName('rebuild') + ->setDescription('rebuild api classes by parsing the official api doc') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->builder->__invoke()->build(); + + $output->writeln('updated Api Classes in src/Api'); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Console/ApiCommand.php b/www/multitube/vendor/ipfs/php-client/src/Console/ApiCommand.php new file mode 100644 index 0000000..df2bcda --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Console/ApiCommand.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Console; + +use IPFS\Driver\Http; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Input\InputOption; + +class ApiCommand extends Command +{ + public function mergeApplicationDefinition($mergeArgs = true) + { + $originalOptions = $this->getApplication()->getDefinition()->getOptions(); + $this->getApplication()->getDefinition()->setOptions([]); + + parent::mergeApplicationDefinition($mergeArgs); + + foreach ($originalOptions as $option) { + try { + $this->getDefinition()->addOption($option); + } catch (LogicException $e) { + //option already defined by command itself + } + } + + $this->getDefinition()->addOption(new InputOption('--driver', '', InputOption::VALUE_REQUIRED, 'which driver to use', Http::class)); + + $this->getApplication()->getDefinition()->setOptions($originalOptions); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Console/CommandBuilder.php b/www/multitube/vendor/ipfs/php-client/src/Console/CommandBuilder.php new file mode 100644 index 0000000..4ad1e40 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Console/CommandBuilder.php @@ -0,0 +1,158 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Console; + +use ArgumentsResolver\NamedArgumentsResolver; +use IPFS\Api; +use IPFS\Client; +use IPFS\Driver\Driver; +use IPFS\Utils\AnnotationReader; +use IPFS\Utils\CaseFormatter; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +class CommandBuilder +{ + /** + * @var array|Api\Api[] + */ + private $apis; + /** + * @var AnnotationReader + */ + private $reader; + /** + * @var array|\Closure[] + */ + private $drivers = []; + + public function __construct(array $apis, AnnotationReader $reader) + { + $this->apis = $apis; + $this->reader = $reader; + } + + /** + * @return array|ApiCommand[] + */ + public function generateCommands(): array + { + $commands = []; + + foreach ($this->apis as $class) { + $api = new \ReflectionClass($class); + + foreach ($api->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { + if ($this->reader->isApi($method)) { + $command = $this->generateCommand($class, $api->getShortName(), $method); + $commands[$command->getName()] = $command; + } + } + } + + return $commands; + } + + private function generateCommand(Api\Api $api, string $name, \ReflectionMethod $method): Command + { + $command = new ApiCommand(strtolower($this->reader->getName($method))); + + return $command + ->setDefinition($this->buildDefinition($method)) + ->setDescription($this->reader->getDescription($method)) + ->setCode($this->createCode($api, $name, $method)) + ; + } + + private function buildDefinition(\ReflectionMethod $method): InputDefinition + { + $definition = new InputDefinition(); + + $parameters = $this->reader->getParameters($method); + + foreach ($parameters as $name => $param) { + $name = CaseFormatter::camelToDash($name); + + if ($param->hasDefault()) { + $mode = InputOption::VALUE_NONE; + $default = $param->getDefault(); + + if (true === $default || is_string($default)) { + $mode = InputOption::VALUE_OPTIONAL; + } elseif (is_bool($default)) { + $default = null; + } elseif (!is_string($default)) { + $mode = InputOption::VALUE_REQUIRED; + } + + $definition->addOption(new InputOption($name, null, $mode, $param->getDescription(), $default)); + + continue; + } + + $definition->addArgument(new InputArgument($name, InputArgument::REQUIRED, $param->getDescription(), null)); + } + + return $definition; + } + + private function createCode(Api\Api $api, $name, \ReflectionMethod $method): \Closure + { + return function (InputInterface $input, OutputInterface $output) use ($name, $method, $api) { + $fn = $method->getClosure($api); + + $options = CaseFormatter::dashToCamelArray($input->getOptions()); + $arguments = CaseFormatter::dashToCamelArray($input->getArguments()); + + $args = (new NamedArgumentsResolver($method))->resolve(array_merge($options, $arguments)); + $args = $this->sanitizeArguments($args); + + $client = new Client($this->chooseClient($input->getOption('driver'))); + $response = $client->execute($fn(...$args)); + + $output->writeln($response); + }; + } + + public function addDriver(string $name, \Closure $driver): CommandBuilder + { + $this->drivers[$name] = $driver; + + return $this; + } + + private function chooseClient(string $class): Driver + { + if (!isset($this->drivers[$class])) { + throw new \InvalidArgumentException(sprintf('"%s" is an unknown Driver, please add it with "addDriver"', $class)); + } + + //the driver is injected as Closure to allow lazy instantiation + + return $this->drivers[$class]->__invoke(); + } + + private function sanitizeArguments(array $args): array + { + foreach ($args as $index => $value) { + $args[$index] = CaseFormatter::stringToBool($value); + } + + return $args; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Container/ServiceProvider.php b/www/multitube/vendor/ipfs/php-client/src/Container/ServiceProvider.php new file mode 100644 index 0000000..5380406 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Container/ServiceProvider.php @@ -0,0 +1,144 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Container; + +use Http\Client\Common\PluginClient; +use Http\Client\HttpAsyncClient; +use Http\Discovery\HttpAsyncClientDiscovery; +use Http\Discovery\MessageFactoryDiscovery; +use Http\Discovery\UriFactoryDiscovery; +use Http\Message\MessageFactory; +use Http\Message\UriFactory; +use IPFS\Api; +use IPFS\Console\ApiBuildCommand; +use IPFS\Console\CommandBuilder; +use IPFS\Driver\Cli; +use IPFS\Driver\Http; +use IPFS\Utils\AnnotationReader; +use phpDocumentor\Reflection\DocBlockFactory; +use PhpParser\BuilderFactory; +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use Symfony\Component\Console\Application; +use Symfony\Component\DomCrawler\Crawler; +use Symfony\Component\Process\Process; + +class ServiceProvider implements ServiceProviderInterface +{ + /** + * {@inheritdoc} + */ + public function register(Container $pimple) + { + $this->registerDriver($pimple); + $this->registerConsole($pimple); + + $pimple[AnnotationReader::class] = function () { + return new AnnotationReader( + new \Doctrine\Common\Annotations\AnnotationReader(), + DocBlockFactory::createInstance() + ); + }; + + $pimple[Api\ApiBuilder::class] = function () use ($pimple) { + $this->registerHttp($pimple); + + $parser = new Api\ApiParser($pimple[HttpAsyncClient::class], $pimple[MessageFactory::class], new Crawler()); + $generator = new Api\ApiGenerator(new BuilderFactory()); + + return new Api\ApiBuilder($parser, $generator); + }; + } + + public function registerHttp(Container $pimple) + { + $pimple[HttpAsyncClient::class] = function () { + return new PluginClient( + HttpAsyncClientDiscovery::find(), + [] + ); + }; + + $pimple[MessageFactory::class] = function () { + return MessageFactoryDiscovery::find(); + }; + + $pimple[UriFactory::class] = function () { + return UriFactoryDiscovery::find(); + }; + } + + private function registerDriver(Container $pimple) + { + $pimple[Http::class] = function () use ($pimple) { + $this->registerHttp($pimple); + + return new Http( + $pimple[HttpAsyncClient::class], + $pimple[MessageFactory::class], + $pimple[UriFactory::class], + $pimple[AnnotationReader::class], + getenv('IPFS_API') ?: 'http://localhost:5001/api/v0' + ); + }; + + $pimple[Cli::class] = function () use ($pimple) { + return new Cli(new Process([]), $pimple[AnnotationReader::class], getenv('IPFS_BINARY') ?: 'ipfs'); + }; + } + + private function registerConsole(Container $pimple) + { + $pimple[CommandBuilder::class] = function (Container $pimple) { + $builder = new CommandBuilder([ + new Api\Basics(), + new Api\Bitswap(), + new Api\Block(), + new Api\Bootstrap(), + new Api\Config(), + new Api\Dag(), + new Api\Dht(), + new Api\Diag(), + new Api\File(), + new Api\Files(), + new Api\Filestore(), + new Api\Key(), + new Api\Log(), + new Api\Name(), + new Api\CObject(), + new Api\P2p(), + new Api\Pin(), + new Api\Pubsub(), + new Api\Refs(), + new Api\Repo(), + new Api\Stats(), + new Api\Swarm(), + new Api\Tar(), + ], $pimple[AnnotationReader::class]); + + $builder->addDriver(Cli::class, $pimple->raw(Cli::class)); + $builder->addDriver(Http::class, $pimple->raw(Http::class)); + + return $builder; + }; + + $pimple[Application::class] = function (Container $pimple) { + $app = new Application('ipfs', '@git-version@'); + $app->addCommands($pimple[CommandBuilder::class]->generateCommands()); + $app->add(new ApiBuildCommand($pimple->raw(Api\ApiBuilder::class))); + + return $app; + }; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Driver/Cli.php b/www/multitube/vendor/ipfs/php-client/src/Driver/Cli.php new file mode 100644 index 0000000..1799e65 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Driver/Cli.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Driver; + +use IPFS\Command\Command; +use IPFS\Utils\AnnotationReader; +use IPFS\Utils\CaseFormatter; +use Symfony\Component\Process\Process; + +class Cli implements Driver +{ + /** + * @var Process + */ + private $builder; + /** + * @var string + */ + private $binary; + /** + * @var AnnotationReader + */ + private $reader; + + public function __construct(Process $builder, AnnotationReader $reader, $binary = 'ipfs') + { + $this->builder = $builder; + $this->binary = $binary; + $this->reader = $reader; + } + + public function execute(Command $command) + { + //SYMFONY 3.2 compat + $script = implode(' ', array_map(['\\Symfony\\Component\\Process\\ProcessUtils', 'escapeArgument'], $this->buildCommand($command))); + + $process = $this->builder + ->setCommandLine($script) + ->enableOutput() + ->inheritEnvironmentVariables() + ->setWorkingDirectory(getenv('CWD')) + ; + + $process->start(); + $process->wait(); + + return $process->getOutput() ?: $process->getErrorOutput(); + } + + private function buildCommand(Command $command): array + { + return array_merge( + [$this->binary], + explode(':', $command->getAction()), + $this->parseParameters($command) + ); + } + + private function parseParameters(Command $command): array + { + $parameters = $this->reader->getParameters($command->getMethod()); + + $parsedParameters = []; + + foreach ($command->getArguments() as $name => $value) { + if ($parameters[$name]->hasDefault() && $parameters[$name]->getDefault() !== $value) { + $parsedParameters[] = sprintf('--%s=%s', CaseFormatter::camelToDash($name), var_export($value, true)); + continue; + } + + if (!$parameters[$name]->hasDefault()) { + $parsedParameters[] = $value; + continue; + } + } + + return $parsedParameters; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Driver/Driver.php b/www/multitube/vendor/ipfs/php-client/src/Driver/Driver.php new file mode 100644 index 0000000..4f47765 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Driver/Driver.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Driver; + +use IPFS\Command\Command; + +interface Driver +{ + public function execute(Command $command); +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Driver/Http.php b/www/multitube/vendor/ipfs/php-client/src/Driver/Http.php new file mode 100644 index 0000000..4ab1cef --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Driver/Http.php @@ -0,0 +1,140 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Driver; + +use Http\Client\HttpAsyncClient; +use Http\Message\MessageFactory; +use Http\Message\MultipartStream\MultipartStreamBuilder; +use Http\Message\UriFactory; +use IPFS\Command\Command; +use IPFS\Utils\AnnotationReader; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\UriInterface; + +class Http implements Driver +{ + /** + * @var HttpAsyncClient + */ + private $client; + /** + * @var MessageFactory + */ + private $messageFactory; + /** + * @var UriFactory + */ + private $uriFactory; + /** + * @var string + */ + private $baseUri; + /** + * @var AnnotationReader + */ + private $reader; + + public function __construct(HttpAsyncClient $client, MessageFactory $messageFactory, UriFactory $uriFactory, AnnotationReader $reader, $baseUri = 'http://localhost:5001/api/v0') + { + $this->client = $client; + $this->messageFactory = $messageFactory; + $this->uriFactory = $uriFactory; + $this->baseUri = $baseUri; + $this->reader = $reader; + } + + public function execute(Command $command) + { + $request = $this->buildRequest($command, $this->getConfig($command)); + + return $this->client->sendAsyncRequest($request)->then(function (ResponseInterface $response) { + return (string) $response->getBody()->getContents(); + })->wait(); + } + + private function buildRequest(Command $command, $config): RequestInterface + { + $body = $this->buildBody($command); + + return $this->messageFactory->createRequest( + $config['method'], + $this->buildUri($command, $config), + $this->buildHeaders($body), + $body->build() + ); + } + + private function buildUri(Command $command, array $config): UriInterface + { + $uri = $this->uriFactory->createUri($this->baseUri . $config['path']); + $vars = []; + + foreach ($command->getArguments() as $name => $value) { + if (is_string($value) && is_readable($value)) { + continue; + } + + $vars[$name] = $value; + } + + //fix arg1= arg2= to arg= weird but seems to be correct (doubled query variable names) + $query = preg_replace('/(\d+)=/', '=', http_build_query($vars)); + + return $uri->withQuery($query); + } + + private function buildBody(Command $command): MultipartStreamBuilder + { + $builder = new MultipartStreamBuilder(); + + foreach ($command->getArguments() as $name => $value) { + if (is_string($value) && is_readable($value)) { + $builder->addResource($name, fopen($command->getArguments()[$name], 'rb'), [ + 'filename' => $value, + 'headers' => ['Content-Type' => 'application/octet-stream'], + ]); + } + } + + return $builder; + } + + private function buildHeaders(MultipartStreamBuilder $body): array + { + $emptyBody = '--' . $body->getBoundary() . "--\r\n"; + + return [ + 'User-Agent' => 'php-ipfs', + 'Content-Type' => $body->build()->getContents() !== $emptyBody ? 'multipart/form-data; boundary=' . $body->getBoundary() : null, + ]; + } + + private function getConfig(Command $command): array + { + $config = [ + 'path' => '/' . str_replace(':', '/', $this->reader->getName($command->getMethod())), + 'method' => 'GET', + ]; + + foreach ($command->getArguments() as $arg) { + if (is_string($arg) && is_readable($arg)) { + $config['method'] = 'POST'; + break; + } + } + + return $config; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Utils/AnnotationReader.php b/www/multitube/vendor/ipfs/php-client/src/Utils/AnnotationReader.php new file mode 100644 index 0000000..e471879 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Utils/AnnotationReader.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Utils; + +use Doctrine\Common\Annotations\AnnotationReader as BaseReader; +use IPFS\Annotation\Api; +use IPFS\Annotation\Param; +use phpDocumentor\Reflection\DocBlockFactory; + +class AnnotationReader +{ + /** + * @var BaseReader + */ + private $reader; + /** + * @var DocBlockFactory + */ + private $docBlockFactory; + + public function __construct(BaseReader $reader, DocBlockFactory $docBlockFactory) + { + $this->reader = $reader; + $this->docBlockFactory = $docBlockFactory; + } + + public function isApi($method): bool + { + return (bool) $this->getApi($method); + } + + public function getDescription($method): string + { + return $this->docBlockFactory->create($this->getMethod($method))->getSummary(); + } + + public function getName($method): string + { + return (string) $this->getApi($method)->name; + } + + /** + * @return array|Param[] + */ + public function getParameters($method): array + { + $reflection = $this->getMethod($method); + $parameters = []; + $docBlock = $this->docBlockFactory->create($reflection->getDocComment()); + $params = $docBlock->getTagsByName('param'); + + foreach ($reflection->getParameters() as $parameter) { + $parameters[$parameter->name] = new Param( + $parameter->name, + $this->parseParameterDocblock($params, $parameter), + $parameter->isDefaultValueAvailable() ? $parameter->getDefaultValue() : Param::class + ); + } + + return $parameters; + } + + /** + * @return Api|null + */ + private function getApi($method) + { + return $this->reader->getMethodAnnotation( + $this->getMethod($method), + Api::class + ); + } + + private function getMethod($method): \ReflectionMethod + { + if ($method instanceof \ReflectionMethod) { + return $method; + } + + list($api, $method) = explode('::', $method); + + return new \ReflectionMethod($api, $method); + } + + private function parseParameterDocblock(array $params, \ReflectionParameter $parameter): string + { + foreach ($params as $param) { + if ($parameter->name === $param->getVariableName()) { + return $param->getDescription()->render(); + } + } + + return ''; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Utils/CaseFormatter.php b/www/multitube/vendor/ipfs/php-client/src/Utils/CaseFormatter.php new file mode 100644 index 0000000..87b009d --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Utils/CaseFormatter.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Utils; + +use Camel\CaseTransformer; +use Camel\Format\CamelCase; + +class CaseFormatter +{ + public static function camelToColon($value) + { + return (new CaseTransformer(new CamelCase(), new ConfigurableFormatter(':')))->transform($value); + } + + public static function colonToCamel($value) + { + return (new CaseTransformer(new ConfigurableFormatter(':'), new CamelCase()))->transform($value); + } + + public static function dashToCamel($value) + { + return (new CaseTransformer(new ConfigurableFormatter('-'), new CamelCase()))->transform($value); + } + + public static function camelToDash($value) + { + return (new CaseTransformer(new CamelCase(), new ConfigurableFormatter('-')))->transform($value); + } + + public static function dashToCamelArray(array $values): array + { + return array_combine(array_map(function ($name) { + return self::dashToCamel($name); + }, array_keys($values)), array_values($values)); + } + + public static function stringToBool($value) + { + return is_string($value) && in_array(strtolower($value), ['true', 'false'], true) ? filter_var($value, FILTER_VALIDATE_BOOLEAN) : $value; + } +} diff --git a/www/multitube/vendor/ipfs/php-client/src/Utils/ConfigurableFormatter.php b/www/multitube/vendor/ipfs/php-client/src/Utils/ConfigurableFormatter.php new file mode 100644 index 0000000..efd77d0 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/src/Utils/ConfigurableFormatter.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace IPFS\Utils; + +use Camel\Format\FormatInterface; + +class ConfigurableFormatter implements FormatInterface +{ + /** + * @var string + */ + private $delimiter; + + public function __construct(string $delimiter) + { + $this->delimiter = $delimiter; + } + + /** + * {@inheritdoc} + */ + public function split($word) + { + return explode($this->delimiter, $word); + } + + /** + * {@inheritdoc} + */ + public function join(array $words) + { + // Ensure words are lowercase + $words = array_map('strtolower', $words); + + return implode($this->delimiter, $words); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Annotation/ParamSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Annotation/ParamSpec.php new file mode 100644 index 0000000..3b67367 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Annotation/ParamSpec.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Annotation; + +use IPFS\Annotation\Param; +use PhpSpec\ObjectBehavior; + +class ParamSpec extends ObjectBehavior +{ + public function let() + { + $this->beConstructedWith('foo', 'bar', 'lol'); + } + + public function it_is_initializable() + { + $this->shouldHaveType(Param::class); + } + + public function it_has_simple_getters() + { + $this->getName()->shouldBe('foo'); + $this->getDescription()->shouldBe('bar'); + $this->getDefault()->shouldBe('lol'); + } + + public function it_can_check_if_there_is_a_default_value() + { + $this->beConstructedWith('foo', 'bar'); + $this->hasDefault()->shouldBe(false); + $this->getDefault()->shouldBe(null); + } + + public function it_can_check_if_there_is_no_default_value() + { + $this->beConstructedWith('foo', 'bar', 'lol'); + $this->hasDefault()->shouldBe(true); + $this->getDefault()->shouldBe('lol'); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiBuilderSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiBuilderSpec.php new file mode 100644 index 0000000..5556fad --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiBuilderSpec.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Api; + +use IPFS\Api\ApiBuilder; +use IPFS\Api\ApiGenerator; +use IPFS\Api\ApiParser; +use PhpSpec\ObjectBehavior; +use Prophecy\Argument; + +class ApiBuilderSpec extends ObjectBehavior +{ + public function let(ApiParser $parser, ApiGenerator $builder) + { + $this->beConstructedWith($parser, $builder); + } + + public function it_is_initializable() + { + $this->shouldHaveType(ApiBuilder::class); + } + + public function it_invokes_the_parser_and_generator(ApiParser $parser, ApiGenerator $builder) + { + $parser->build(Argument::type('string'), Argument::type('string'))->shouldBeCalled()->willReturn([]); + $builder->build(Argument::type('array'))->shouldBeCalled(); + + $this->build(); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiGeneratorSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiGeneratorSpec.php new file mode 100644 index 0000000..e194c48 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiGeneratorSpec.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Api; + +use IPFS\Api\ApiGenerator; +use PhpParser\BuilderFactory; +use PhpSpec\Exception\Example\NotEqualException; +use PhpSpec\ObjectBehavior; +use Prophecy\Exception\Prediction\FailedPredictionException; + +class ApiGeneratorSpec extends ObjectBehavior +{ + public function let() + { + $this->beConstructedWith(new BuilderFactory(), sys_get_temp_dir()); + } + + public function it_is_initializable() + { + $this->shouldHaveType(ApiGenerator::class); + } + + public function it_generates_valid_php_code_out_of_api_methods() + { + $this->build([ + 'foo' => [ + 'bar' => [ + 'parts' => 'foo:bar', + 'description' => 'foo', + 'class' => 'foo', + 'method' => 'bar', + 'arguments' => [ + [ + 'name' => 'foo', + 'required' => true, + 'description' => 'foo argument', + 'default' => null, + 'type' => 'string', + ], + [ + 'name' => 'bar', + 'required' => false, + 'description' => 'bar argument', + 'default' => false, + 'type' => 'bool', + ], + ], + ], + ], + ]); + + $code = << + * @autogenerated + * @codeCoverageIgnore + */ +final class foo implements Api +{ + /** + * foo + * + * @Endpoint(name="foo:bar") + * + * @param string \$foo foo argument + * @param bool \$bar bar argument + * + * @return Command + */ + public function bar(string \$foo, bool \$bar = false) : Command + { + return new Command(__METHOD__, get_defined_vars()); + } +} +EOS; + $file = sys_get_temp_dir() . '/Foo.php'; + + if (!file_exists($file)) { + throw new FailedPredictionException(sprintf('generated Class "%s"is missing', $file)); + } + + if (file_get_contents($file) !== $code) { + throw new NotEqualException('generated code differs', $code, file_get_contents($file)); + } + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiParserSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiParserSpec.php new file mode 100644 index 0000000..83617a8 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Api/ApiParserSpec.php @@ -0,0 +1,164 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Api; + +use Http\Discovery\HttpAsyncClientDiscovery; +use Http\Discovery\MessageFactoryDiscovery; +use IPFS\Api\ApiParser; +use PhpSpec\Exception\Example\SkippingException; +use PhpSpec\ObjectBehavior; +use Symfony\Component\DomCrawler\Crawler; + +class ApiParserSpec extends ObjectBehavior +{ + public function let() + { + $this->beConstructedWith(HttpAsyncClientDiscovery::find(), MessageFactoryDiscovery::find(), new Crawler()); + } + + public function it_is_initializable() + { + $this->shouldHaveType(ApiParser::class); + } + + public function it_can_parse_the_api_docs_correctly() + { + ob_start(); + @passthru('curl -s -I https://ipfs.io/docs/api/', $response); + ob_end_clean(); + + if (0 !== $response) { + throw new SkippingException('no internet connection available, so skip test'); + } + + $config = $this->build(); + + $config->shouldBeArray(); + $config->shouldHaveKey('Basics'); + $addApi = $config['Basics'][0]; + + $addApi->shouldBeLike([ + 'parts' => 'add', + 'description' => 'Add a file or directory to ipfs.', + 'arguments' => [ + [ + 'name' => 'file', + 'required' => true, + 'description' => 'The path to a file to be added to ipfs.', + 'default' => null, + 'type' => 'string', + ], [ + 'name' => 'recursive', + 'required' => false, + 'description' => 'Add directory paths recursively.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'quiet', + 'required' => false, + 'description' => 'Write minimal output.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'quieter', + 'required' => false, + 'description' => 'Write only final hash.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'silent', + 'required' => false, + 'description' => 'Write no output.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'progress', + 'required' => false, + 'description' => 'Stream progress data.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'trickle', + 'required' => false, + 'description' => 'Use trickle-dag format for dag generation.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'onlyHash', + 'required' => false, + 'description' => 'Only chunk and hash - do not write to disk.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'wrapWithDirectory', + 'required' => false, + 'description' => 'Wrap files with a directory object.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'hidden', + 'required' => false, + 'description' => 'Include files that are hidden.', + 'default' => false, + 'type' => 'bool', + ], [ + 'name' => 'chunker', + 'required' => false, + 'description' => 'Chunking algorithm, size-[bytes] or rabin-[min]-[avg]-[max].', + 'default' => 'size-262144', + 'type' => 'string', + ], [ + 'name' => 'pin', + 'required' => false, + 'description' => 'Pin this object when adding.', + 'default' => true, + 'type' => 'bool', + ], [ + 'name' => 'rawLeaves', + 'required' => false, + 'description' => 'Use raw blocks for leaf nodes.', + 'default' => false, + 'type' => 'bool', + ], + [ + 'name' => 'nocopy', + 'required' => false, + 'description' => 'Add the file using filestore.', + 'default' => false, + 'type' => 'bool', + ], + [ + 'name' => 'fscache', + 'required' => false, + 'description' => 'Check the filestore for pre-existing blocks.', + 'default' => false, + 'type' => 'bool', + ], + [ + 'name' => 'cidVersion', + 'required' => false, + 'description' => 'CID version.', + 'default' => null, + 'type' => 'int', + ], + [ + 'name' => 'hash', + 'required' => false, + 'description' => 'Hash function to use.', + 'default' => 'sha2-256', + 'type' => 'string', + ], ], + 'class' => 'Basics', + 'method' => 'add', + ]); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/ClientSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/ClientSpec.php new file mode 100644 index 0000000..cbbf734 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/ClientSpec.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS; + +use IPFS\Client; +use IPFS\Command\Command; +use IPFS\Driver\Driver; +use PhpSpec\ObjectBehavior; + +class ClientSpec extends ObjectBehavior +{ + public function let(Driver $driver) + { + $this->beConstructedWith($driver); + } + + public function it_is_initializable() + { + $this->shouldHaveType(Client::class); + $this->shouldImplement(Driver::class); + } + + public function it_passes_the_command_to_the_underlying_driver(Driver $driver, Command $command) + { + $driver->execute($command)->shouldBeCalled(); + + $this->execute($command); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Command/CommandSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Command/CommandSpec.php new file mode 100644 index 0000000..f58465f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Command/CommandSpec.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Command; + +use IPFS\Command\Command; +use PhpSpec\ObjectBehavior; + +class CommandSpec extends ObjectBehavior +{ + public function let() + { + $this->beConstructedWith(__CLASS__ . '::fooBarBazz', ['foo', 'bar']); + } + + public function it_is_initializable() + { + $this->shouldHaveType(Command::class); + } + + public function it_has_accessors_for_method_and_arguments() + { + $this->getMethod()->shouldBe(__CLASS__ . '::fooBarBazz'); + $this->getArguments()->shouldBe(['foo', 'bar']); + } + + public function it_can_convert_the_method_to_an_action() + { + $this->getAction()->shouldBe('command:spec:foo:bar:bazz'); + } + + public function it_will_revert_reserved_keywords_workaround() + { + $this->beConstructedWith('cobject' . '::fooBarBazz'); + + $this->getAction()->shouldBe('object:foo:bar:bazz'); + } + + public function it_will_strip_basic_commands() + { + $this->beConstructedWith('basics' . '::fooBarBazz'); + + $this->getAction()->shouldBe('foo:bar:bazz'); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiBuildCommandSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiBuildCommandSpec.php new file mode 100644 index 0000000..1dfc055 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiBuildCommandSpec.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Console; + +use IPFS\Api\ApiBuilder; +use IPFS\Console\ApiBuildCommand; +use PhpSpec\ObjectBehavior; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +class ApiBuildCommandSpec extends ObjectBehavior +{ + public function let(ApiBuilder $builder) + { + $this->beConstructedWith(function () use ($builder) { + return $builder->getWrappedObject(); + }); + } + + public function it_is_initializable() + { + $this->shouldHaveType(ApiBuildCommand::class); + $this->shouldHaveType(Command::class); + } + + public function it_has_a_descriptive_name() + { + $this->getName()->shouldBe('rebuild'); + } + + public function it_calls_the_builder(ApiBuilder $builder, InputInterface $input, OutputInterface $output) + { + $this->run($input, $output); + + $builder->build()->shouldHaveBeenCalled(); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiCommandSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiCommandSpec.php new file mode 100644 index 0000000..dfc943b --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/ApiCommandSpec.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Console; + +use IPFS\Console\ApiCommand; +use PhpSpec\ObjectBehavior; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +class ApiCommandSpec extends ObjectBehavior +{ + public function let() + { + $this->beConstructedWith('foo'); + + $this->setApplication(new Application()); + + $definition = new InputDefinition([ + new InputOption('--quiet', null, InputOption::VALUE_NONE, 'my own quiet'), + ]); + + $this->setDefinition($definition); + } + + public function it_is_initializable() + { + $this->shouldHaveType(ApiCommand::class); + $this->shouldHaveType(Command::class); + } + + public function it_only_appends_the_default_options_if_they_are_not_already_exists() + { + $this->mergeApplicationDefinition(true); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Console/CommandBuilderSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/CommandBuilderSpec.php new file mode 100644 index 0000000..8b82d6e --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Console/CommandBuilderSpec.php @@ -0,0 +1,85 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Console; + +use IPFS\Console\ApiCommand; +use IPFS\Console\CommandBuilder; +use IPFS\Container\ServiceProvider; +use IPFS\Driver\Driver; +use IPFS\Utils\AnnotationReader; +use phpDocumentor\Reflection\DocBlockFactory; +use PhpSpec\ObjectBehavior; +use Pimple\Container; +use Prophecy\Argument; +use spec\IPFS\TestApi; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\OutputInterface; + +class CommandBuilderSpec extends ObjectBehavior +{ + public function let() + { + $container = new Container(); + $provider = new ServiceProvider(); + $provider->register($container); + + $this->beConstructedWith( + [new TestApi()], + new AnnotationReader(new \Doctrine\Common\Annotations\AnnotationReader(), DocBlockFactory::createInstance()) + ); + } + + public function it_is_initializable() + { + $this->shouldHaveType(CommandBuilder::class); + } + + public function it_builds_symfony_commands_from_the_apis() + { + $commands = $this->generateCommands(); + + $commands->shouldHaveKey('test:foo'); + $command = $commands['test:foo']; + /* @var ApiCommand $command */ + + $command->shouldHaveType(ApiCommand::class); + $command->getName()->shouldBe('test:foo'); + $command->getDescription()->shouldBe('this is a description.'); + + $command->getDefinition()->hasOption('bazz'); + $command->getDefinition()->getOption('bazz')->getDefault()->shouldBe(false); + $command->getDefinition()->getOption('bazz')->getDescription()->shouldBe('bazz'); + + $command->getDefinition()->hasOption('lol'); + $command->getDefinition()->getOption('lol')->getDefault()->shouldBe(1); + $command->getDefinition()->getOption('lol')->getDescription()->shouldBe('lol'); + + $command->getDefinition()->hasArgument('bar'); + $command->getDefinition()->getArgument('bar')->isRequired()->shouldBe(true); + $command->getDefinition()->getArgument('bar')->getDescription()->shouldBe('bar'); + } + + public function it_invokes_the_driver_on_run(Driver $driver, OutputInterface $output) + { + $this->getWrappedObject()->addDriver(get_class($driver->getWrappedObject()), function () use ($driver) { + return $driver->getWrappedObject(); + }); + + $command = $this->generateCommands()['test:foo']; + $command->setApplication(new Application()); + + $command->run(new ArrayInput(['bar' => 'real value', '--driver' => get_class($driver->getWrappedObject())]), $output); + + $output->writeln(Argument::any())->shouldBeCalled(); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Container/ServiceProviderSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Container/ServiceProviderSpec.php new file mode 100644 index 0000000..9772f8d --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Container/ServiceProviderSpec.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Container; + +use IPFS\Container\ServiceProvider; +use PhpSpec\ObjectBehavior; +use Pimple\Container; +use Pimple\ServiceProviderInterface; +use Prophecy\Argument; + +class ServiceProviderSpec extends ObjectBehavior +{ + public function it_is_initializable() + { + $this->shouldHaveType(ServiceProvider::class); + $this->shouldImplement(ServiceProviderInterface::class); + } + + public function it_registers_services(Container $container) + { + $container->offsetSet(Argument::type('string'), Argument::type('callable'))->shouldBeCalled(); + + $this->register($container); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/CliSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/CliSpec.php new file mode 100644 index 0000000..0142ed3 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/CliSpec.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Driver; + +use IPFS\Command\Command; +use IPFS\Driver\Cli; +use IPFS\Driver\Driver; +use IPFS\Utils\AnnotationReader; +use phpDocumentor\Reflection\DocBlockFactory; +use PhpSpec\ObjectBehavior; +use Symfony\Component\Process\Process; + +class CliSpec extends ObjectBehavior +{ + const METHOD = 'spec\IPFS\TestApi::foo'; + + public function let() + { + $this->beConstructedWith( + new Process([]), + new AnnotationReader(new \Doctrine\Common\Annotations\AnnotationReader(), DocBlockFactory::createInstance()), + 'echo' + ); + } + + public function it_is_initializable() + { + $this->shouldHaveType(Cli::class); + $this->shouldImplement(Driver::class); + } + + public function it_creates_a_cli_command_and_passes_it_to_the_binary() + { + $this->execute(new Command(self::METHOD, ['bar' => 'bar', 'bazz' => true, 'lol' => 10]))->shouldBe("test api foo bar --bazz=true --lol=10\n"); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/HttpSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/HttpSpec.php new file mode 100644 index 0000000..62d7d6f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Driver/HttpSpec.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Driver; + +use Http\Client\HttpAsyncClient; +use Http\Discovery\MessageFactoryDiscovery; +use Http\Discovery\UriFactoryDiscovery; +use Http\Promise\Promise; +use IPFS\Command\Command; +use IPFS\Driver\Driver; +use IPFS\Driver\Http; +use IPFS\Utils\AnnotationReader; +use phpDocumentor\Reflection\DocBlockFactory; +use PhpSpec\ObjectBehavior; +use Prophecy\Argument; +use Psr\Http\Message\RequestInterface; + +class HttpSpec extends ObjectBehavior +{ + const METHOD = 'spec\IPFS\TestApi::foo'; + + public function let(HttpAsyncClient $client) + { + $this->beConstructedWith( + $client, + MessageFactoryDiscovery::find(), + UriFactoryDiscovery::find(), + new AnnotationReader(new \Doctrine\Common\Annotations\AnnotationReader(), DocBlockFactory::createInstance()) + ); + } + + public function it_is_initializable() + { + $this->shouldHaveType(Http::class); + $this->shouldImplement(Driver::class); + } + + public function it_creates_a_http_uri_from_the_command_and_calls_the_rest_api(HttpAsyncClient $client, Promise $promise) + { + $client->sendAsyncRequest(Argument::that(function (RequestInterface $request) { + return 'bar=bar&bazz=1&lol=10' === $request->getUri()->getQuery() && + '/api/v0/test/foo' === $request->getUri()->getPath() + ; + }))->willReturn($promise); + + $promise->then(Argument::type('callable'))->willReturn($promise); + $promise->wait()->shouldBeCalled(); + + $this->execute(new Command(self::METHOD, ['bar' => 'bar', 'bazz' => true, 'lol' => 10]))->shouldBe(null); + } + + public function it_can_attach_variables_that_are_file_locations_as_multipart_form_data_to_the_request(HttpAsyncClient $client, Promise $promise) + { + $client->sendAsyncRequest(Argument::that(function (RequestInterface $request) { + $body = $request->getBody()->getContents(); + + return 'bazz=1&lol=10' === $request->getUri()->getQuery() && + '/api/v0/test/foo' === $request->getUri()->getPath() && + false !== strpos($request->getHeaders()['Content-Type'][0], 'multipart/form-data; boundary=') && + false !== strpos($body, 'Content-Type: application/octet-stream') && + false !== strpos($body, 'Content-Disposition: form-data; name="bar"; filename="HttpSpec.php"') + ; + }))->willReturn($promise); + + $promise->then(Argument::type('callable'))->willReturn($promise); + $promise->wait()->shouldBeCalled(); + + $this->execute(new Command(self::METHOD, ['bar' => __FILE__, 'bazz' => true, 'lol' => 10]))->shouldBe(null); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/TestApi.php b/www/multitube/vendor/ipfs/php-client/tests/spec/TestApi.php new file mode 100644 index 0000000..8dc1e66 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/TestApi.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS; + +use IPFS\Annotation\Api as Endpoint; +use IPFS\Api\Api; +use IPFS\Command\Command; + +class TestApi implements Api +{ + /** + * this is a description. + * + * @Endpoint(name="test:foo") + * + * @param string $bar bar + * @param bool $bazz bazz + * @param int $lol lol + */ + public function foo(string $bar, bool $bazz = false, int $lol = 1) + { + return new Command(__METHOD__, get_defined_vars()); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/AnnotationReaderSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/AnnotationReaderSpec.php new file mode 100644 index 0000000..c627534 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/AnnotationReaderSpec.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Utils; + +use IPFS\Annotation\Param; +use IPFS\Utils\AnnotationReader; +use phpDocumentor\Reflection\DocBlockFactory; +use PhpSpec\ObjectBehavior; + +class AnnotationReaderSpec extends ObjectBehavior +{ + const METHOD = 'spec\IPFS\TestApi::foo'; + + public function let() + { + $this->beConstructedWith(new \Doctrine\Common\Annotations\AnnotationReader(), DocBlockFactory::createInstance()); + } + + public function it_is_initializable() + { + $this->shouldHaveType(AnnotationReader::class); + } + + public function it_can_handle__METHOD___constant_as_input() + { + $this->isApi(self::METHOD)->shouldBe(true); + } + + public function it_can_handle_reflections_as_input() + { + $reflection = new \ReflectionMethod(self::METHOD); + $this->isApi($reflection)->shouldBe(true); + } + + public function it_can_parse_the_description_from_the_docblock() + { + $this->getDescription(self::METHOD)->shouldBe('this is a description.'); + } + + public function it_can_parse_the_name_from_the_annotation() + { + $this->getName(self::METHOD)->shouldBe('test:foo'); + } + + public function it_can_the_method_parameters() + { + $parameters = $this->getParameters(self::METHOD); + + $parameters->shouldHaveCount(3); + + $parameters['bar']->shouldHaveType(Param::class); + $parameters['bar']->hasDefault()->shouldBe(false); + $parameters['bar']->getName()->shouldBe('bar'); + $parameters['bar']->getDescription()->shouldBe('bar'); + + $parameters['bazz']->shouldHaveType(Param::class); + $parameters['bazz']->hasDefault()->shouldBe(true); + $parameters['bazz']->getDefault()->shouldBe(false); + $parameters['bazz']->getName()->shouldBe('bazz'); + $parameters['bazz']->getDescription()->shouldBe('bazz'); + + $parameters['lol']->shouldHaveType(Param::class); + $parameters['lol']->hasDefault()->shouldBe(true); + $parameters['lol']->getDefault()->shouldBe(1); + $parameters['lol']->getName()->shouldBe('lol'); + $parameters['lol']->getDescription()->shouldBe('lol'); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/CaseFormatterSpec.php b/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/CaseFormatterSpec.php new file mode 100644 index 0000000..5883f2f --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/Utils/CaseFormatterSpec.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace spec\IPFS\Utils; + +use IPFS\Utils\CaseFormatter; +use PhpSpec\ObjectBehavior; + +class CaseFormatterSpec extends ObjectBehavior +{ + public function it_is_initializable() + { + $this->shouldHaveType(CaseFormatter::class); + } + + public function it_can_convert_camelCase_to_colonCase_and_vice_versa() + { + $this->camelToColon('fooBar')->shouldBe('foo:bar'); + $this->colonToCamel('foo:bar')->shouldBe('fooBar'); + } + + public function it_can_convert_camelCase_to_dashCase_and_vice_versa() + { + $this->camelToDash('fooBar')->shouldBe('foo-bar'); + $this->dashToCamel('foo-bar')->shouldBe('fooBar'); + } + + public function it_can_convert_string_representations_of_booleans_to_booleans() + { + $this->stringToBool('True')->shouldBe(true); + $this->stringToBool('true')->shouldBe(true); + $this->stringToBool('false')->shouldBe(false); + $this->stringToBool('FALSE')->shouldBe(false); + + $this->stringToBool('foo')->shouldBe('foo'); + } + + public function it_can_convert_all_values_from_an_array_from_dash_to_camel() + { + $this->dashToCamelArray(['foo-bar' => 'foo', 'bar-bazz-lol' => 'bar'])->shouldBe(['fooBar' => 'foo', 'barBazzLol' => 'bar']); + } +} diff --git a/www/multitube/vendor/ipfs/php-client/tests/spec/bootstrap.php b/www/multitube/vendor/ipfs/php-client/tests/spec/bootstrap.php new file mode 100644 index 0000000..47ccc27 --- /dev/null +++ b/www/multitube/vendor/ipfs/php-client/tests/spec/bootstrap.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +$loader = require __DIR__ . '/../../vendor/autoload.php'; + +use Doctrine\Common\Annotations\AnnotationRegistry; + +AnnotationRegistry::registerLoader([$loader, 'loadClass']); diff --git a/www/multitube/vendor/mattketmo/camel/.gitignore b/www/multitube/vendor/mattketmo/camel/.gitignore new file mode 100644 index 0000000..a79486f --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/.gitignore @@ -0,0 +1,3 @@ +vendor +composer.lock +phpunit.xml diff --git a/www/multitube/vendor/mattketmo/camel/.travis.yml b/www/multitube/vendor/mattketmo/camel/.travis.yml new file mode 100644 index 0000000..ea3428b --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/.travis.yml @@ -0,0 +1,8 @@ +language: php + +php: + - 5.3 + - 5.4 + +before_script: + - composer install diff --git a/www/multitube/vendor/mattketmo/camel/LICENSE b/www/multitube/vendor/mattketmo/camel/LICENSE new file mode 100644 index 0000000..9299f5a --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 Matthieu Moquet + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/mattketmo/camel/README.md b/www/multitube/vendor/mattketmo/camel/README.md new file mode 100644 index 0000000..d0ccf13 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/README.md @@ -0,0 +1,63 @@ +# Camel + +[![Build status...](https://img.shields.io/travis/MattKetmo/camel.svg?style=flat)](http://travis-ci.org/MattKetmo/camel) +[![Code quality...](https://img.shields.io/scrutinizer/g/MattKetmo/camel.svg?style=flat)](https://scrutinizer-ci.com/g/MattKetmo/camel/) +[![License MIT](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/MattKetmo/camel/blob/master/LICENSE) +[![Packagist](http://img.shields.io/packagist/v/mattketmo/camel.svg?style=flat)](https://packagist.org/packages/mattketmo/camel) + +Tiny library to handle words case transformation. + +The main idea is to split the given word into several words and assemble them +in another format. + +Example: `camelCase => [camel, Case] => camel_case` + +## Installation + +```shell +composer require mattketmo/camel +``` + +## Usage + +```php +transform('hello_world'); // helloWorld +echo $transformer2->transform('helloWorld'); // HELLO_WORLD +``` + +## Supported formats + +- `camelCase` +- `StudlyCaps` +- `snake_case` +- `SCREAMING_SNAKE_CASE` +- `spinal-case` + +## Unit Tests + +Install `phpunit` via Composer: + +```shell +composer install +``` + +Once installed, run the following command: + +```shell +vendor/bin/phpunit +``` + +## License + +Camel is released under the MIT License. +See the [bundled LICENSE file](LICENSE) for details. diff --git a/www/multitube/vendor/mattketmo/camel/composer.json b/www/multitube/vendor/mattketmo/camel/composer.json new file mode 100644 index 0000000..5f98a43 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/composer.json @@ -0,0 +1,20 @@ +{ + "name": "mattketmo/camel", + "description": "Tiny library to handle words case transformation", + "license": "MIT", + "keywords": ["case", "transform", "camelcase", "snakecase", "lowercase"], + "authors": [ + { + "name": "Matthieu Moquet", + "email": "matthieu@moquet.net" + } + ], + "autoload": { + "psr-0": { + "Camel": "src/" + } + }, + "require-dev": { + "phpunit/phpunit": "4.6.*" + } +} diff --git a/www/multitube/vendor/mattketmo/camel/phpunit.xml.dist b/www/multitube/vendor/mattketmo/camel/phpunit.xml.dist new file mode 100644 index 0000000..84ae620 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/phpunit.xml.dist @@ -0,0 +1,29 @@ + + + + + + tests + + + + + + . + + tests + vendor + + + + diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformer.php b/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformer.php new file mode 100644 index 0000000..d255f71 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformer.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel; + +use Camel\Format\FormatInterface; + +/** + * Global transformer used to manage format conversion. + * + * @author Matthieu Moquet + */ +class CaseTransformer implements CaseTransformerInterface +{ + /** + * @var FormatInterface Initial case format + */ + protected $from; + + /** + * @var FormatInterface Final case format + */ + protected $to; + + /** + * @param FormatInterface $from + * @param FormatInterface $to + */ + public function __construct(FormatInterface $from, FormatInterface $to) + { + $this->from = $from; + $this->to = $to; + } + + /** + * {@inheritdoc} + */ + public function transform($word) + { + $words = $this->from->split($word); + + return $this->to->join($words); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformerInterface.php b/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformerInterface.php new file mode 100644 index 0000000..554eab6 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/CaseTransformerInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel; + +/** + * Transform the case of a word. + * + * @author Matthieu Moquet + */ +interface CaseTransformerInterface +{ + /** + * Transform a word from a case format to an other. + * + * @param string $word The initial word + * + * @return string The transformed word + */ + public function transform($word); +} \ No newline at end of file diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/CamelCase.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/CamelCase.php new file mode 100644 index 0000000..fa326b8 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/CamelCase.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Format to handle camelCase. + * + * @author Matthieu Moquet + */ +class CamelCase extends StudlyCaps +{ + /** + * {@inheritdoc} + */ + public function join(array $words) + { + return lcfirst(parent::join($words)); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/FormatInterface.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/FormatInterface.php new file mode 100644 index 0000000..e06a60c --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/FormatInterface.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Handler to convert from a case to another. + * + * The idea is to split the given word into several words and then assemble them + * with another format. + * + * Example: camelCase => [camel, Case] => camel_case + * + * @author Matthie Moquet + */ +interface FormatInterface +{ + /** + * Split a word in the initial case into several words. + * + * @param string $word The initial word + * + * @return array An array of string + */ + public function split($word); + + /** + * Joins array of words to render the desired case. + * + * @param array words Array of string + * + * @return string The final word + */ + public function join(array $words); +} diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/ScreamingSnakeCase.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/ScreamingSnakeCase.php new file mode 100644 index 0000000..96250cf --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/ScreamingSnakeCase.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Format to handle SCREAMING_SNAKE_CASE. + * + * @author Matthieu Moquet + */ +class ScreamingSnakeCase extends SnakeCase +{ + /** + * {@inheritdoc} + */ + public function join(array $words) + { + return strtoupper(parent::join($words)); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SnakeCase.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SnakeCase.php new file mode 100644 index 0000000..d949f2d --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SnakeCase.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Format to handle sneak_case. + * + * @author Matthieu Moquet + */ +class SnakeCase implements FormatInterface +{ + /** + * {@inheritdoc} + */ + public function split($word) + { + return explode('_', $word); + } + + /** + * {@inheritdoc} + */ + public function join(array $words) + { + // Ensure words are lowercase + $words = array_map('strtolower', $words); + + return implode('_', $words); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SpinalCase.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SpinalCase.php new file mode 100644 index 0000000..4d16012 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/SpinalCase.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Format to handle spinal-case. + * + * @author Denis Roussel + */ +class SpinalCase implements FormatInterface +{ + /** + * {@inheritdoc} + */ + public function split($word) + { + return explode('-', $word); + } + + /** + * {@inheritdoc} + */ + public function join(array $words) + { + // Ensure words are lowercase + $words = array_map('strtolower', $words); + + return implode('-', $words); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/src/Camel/Format/StudlyCaps.php b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/StudlyCaps.php new file mode 100644 index 0000000..0cc3f2c --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/src/Camel/Format/StudlyCaps.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Format; + +/** + * Format to handle StudlyCaps. + * + * @author Matthieu Moquet + */ +class StudlyCaps implements FormatInterface +{ + /** + * {@inheritdoc} + */ + public function split($word) + { + // Match camelCase + $pattern = '/ # Match position between camelCase "words". + (?<=[a-z]) # Position is after a lowercase, + (?=[A-Z]) # and before an uppercase letter. + /x'; + + $words = preg_split($pattern, $word); + + return $words; + } + + /** + * {@inheritdoc} + */ + public function join(array $words) + { + // Ensure words are lowercase + $words = array_map('strtolower', $words); + + // UC first each words + $words = array_map('ucfirst', $words); + + return implode('', $words); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/CaseTransformerTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/CaseTransformerTest.php new file mode 100644 index 0000000..ea26c2c --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/CaseTransformerTest.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests; + +use Camel\CaseTransformer; +use Camel\Format; + +class CaseTransformerTest extends \PHPUnit_Framework_TestCase +{ + public function testTransform() + { + $camelCase = new Format\CamelCase(); + $snakeCase = new Format\SnakeCase(); + + $transformer = new CaseTransformer($camelCase, $snakeCase); + $this->assertEquals('hello_world', $transformer->transform('helloWorld')); + + $transformer = new CaseTransformer($snakeCase, $camelCase); + $this->assertEquals('helloWorld', $transformer->transform('hello_world')); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/CamelCaseTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/CamelCaseTest.php new file mode 100644 index 0000000..f8d0c60 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/CamelCaseTest.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +use Camel\Format\CamelCase; + +class CamelCaseTest extends FormatTest +{ + public function getFormatInstance() + { + return new CamelCase(); + } + + public function provideValidJoins() + { + return array( + array(array('hello', 'world'), 'helloWorld'), + array(array('HeLlO', 'wOrLd'), 'helloWorld'), + array(array('HELLO', 'WORLD'), 'helloWorld'), + array(array('hello', 'my', 'world'), 'helloMyWorld'), + ); + } + + public function provideValidSplits() + { + return array( + array('helloWorld', array('hello', 'World')), + array('helloMyWorld', array('hello', 'My', 'World')), + ); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/FormatTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/FormatTest.php new file mode 100644 index 0000000..54d634f --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/FormatTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +abstract class FormatTest extends \PHPUnit_Framework_TestCase +{ + protected $format; + + public function setUp() + { + $this->format = $this->getFormatInstance(); + } + + /** + * @dataProvider provideValidJoins + */ + public function testJoin(array $inputWords, $expectedWord) + { + $this->assertEquals($this->format->join($inputWords), $expectedWord); + } + + /** + * @dataProvider provideValidSplits + */ + public function testSplit($inputWord, array $expectedWords) + { + $this->assertEquals($this->format->split($inputWord), $expectedWords); + } + + abstract public function getFormatInstance(); + + abstract public function provideValidJoins(); + + abstract public function provideValidSplits(); +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/ScreamingSnakeCaseTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/ScreamingSnakeCaseTest.php new file mode 100644 index 0000000..0935856 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/ScreamingSnakeCaseTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +use Camel\Format\ScreamingSnakeCase; + +class ScreamingSnakeCaseTest extends FormatTest +{ + public function getFormatInstance() + { + return new ScreamingSnakeCase(); + } + + public function provideValidJoins() + { + return array( + array(array('hello', 'world'), 'HELLO_WORLD'), + array(array('HeLlO', 'wOrLd'), 'HELLO_WORLD'), + array(array('HELLO', 'WORLD'), 'HELLO_WORLD'), + array(array('hello', 'my', 'world'), 'HELLO_MY_WORLD'), + ); + } + + public function provideValidSplits() + { + return array( + array('hello_world', array('hello', 'world')), + array('HELLO_WORLD', array('HELLO', 'WORLD')), + array('HELLO_MY_WORLD', array('HELLO', 'MY', 'WORLD')), + ); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SnakeCaseTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SnakeCaseTest.php new file mode 100644 index 0000000..738f4fa --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SnakeCaseTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +use Camel\Format\SnakeCase; + +class SnakeCaseTest extends FormatTest +{ + public function getFormatInstance() + { + return new SnakeCase(); + } + + public function provideValidJoins() + { + return array( + array(array('hello', 'world'), 'hello_world'), + array(array('HeLlO', 'wOrLd'), 'hello_world'), + array(array('HELLO', 'WORLD'), 'hello_world'), + array(array('hello', 'my', 'world'), 'hello_my_world'), + ); + } + + public function provideValidSplits() + { + return array( + array('hello_world', array('hello', 'world')), + array('HELLO_WORLD', array('HELLO', 'WORLD')), + array('hello_my_world', array('hello', 'my', 'world')), + ); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SpinalCaseTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SpinalCaseTest.php new file mode 100644 index 0000000..c84a152 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/SpinalCaseTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +use Camel\Format\SpinalCase; + +class SpinalCaseTest extends FormatTest +{ + public function getFormatInstance() + { + return new SpinalCase(); + } + + public function provideValidJoins() + { + return array( + array(array('hello', 'world'), 'hello-world'), + array(array('HeLlO', 'wOrLd'), 'hello-world'), + array(array('HELLO', 'WORLD'), 'hello-world'), + array(array('hello', 'my', 'world'), 'hello-my-world'), + ); + } + + public function provideValidSplits() + { + return array( + array('hello-world', array('hello', 'world')), + array('HELLO-WORLD', array('HELLO', 'WORLD')), + array('hello-my-world', array('hello', 'my', 'world')), + ); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/StudlyCapsTest.php b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/StudlyCapsTest.php new file mode 100644 index 0000000..5ad4b4a --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/Camel/Tests/Format/StudlyCapsTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Camel\Tests\Format; + +use Camel\Format\StudlyCaps; + +class StudlyCapsTest extends FormatTest +{ + public function getFormatInstance() + { + return new StudlyCaps(); + } + + public function provideValidJoins() + { + return array( + array(array('hello', 'world'), 'HelloWorld'), + array(array('HeLlO', 'wOrLd'), 'HelloWorld'), + array(array('HELLO', 'WORLD'), 'HelloWorld'), + array(array('hello', 'my', 'world'), 'HelloMyWorld'), + ); + } + + public function provideValidSplits() + { + return array( + array('HelloWorld', array('Hello', 'World')), + array('helloWorld', array('hello', 'World')), + array('HelloMyWorld', array('Hello', 'My', 'World')), + ); + } +} diff --git a/www/multitube/vendor/mattketmo/camel/tests/bootstrap.php b/www/multitube/vendor/mattketmo/camel/tests/bootstrap.php new file mode 100644 index 0000000..7ab3ea1 --- /dev/null +++ b/www/multitube/vendor/mattketmo/camel/tests/bootstrap.php @@ -0,0 +1,5 @@ +add('Camel\Tests', __DIR__); diff --git a/www/multitube/vendor/nikic/php-parser/.gitignore b/www/multitube/vendor/nikic/php-parser/.gitignore new file mode 100644 index 0000000..8c7db2a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/.gitignore @@ -0,0 +1,4 @@ +vendor/ +composer.lock +grammar/kmyacc.exe +grammar/y.output diff --git a/www/multitube/vendor/nikic/php-parser/.travis.yml b/www/multitube/vendor/nikic/php-parser/.travis.yml new file mode 100644 index 0000000..9cd0025 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/.travis.yml @@ -0,0 +1,31 @@ +language: php +dist: trusty +sudo: false + +cache: + directories: + - $HOME/.composer/cache + +php: + - 5.5 + - 5.6 + - 7.0 + - nightly + - hhvm + +install: + - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then composer require satooshi/php-coveralls '~1.0'; fi + - composer install --prefer-dist + +matrix: + allow_failures: + - php: nightly + fast_finish: true + +script: + - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then vendor/bin/phpunit --coverage-clover build/logs/clover.xml; else vendor/bin/phpunit; fi + - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then test_old/run-php-src.sh; fi + +after_success: + if [ $TRAVIS_PHP_VERSION = '5.6' ]; then php vendor/bin/coveralls; fi + diff --git a/www/multitube/vendor/nikic/php-parser/CHANGELOG.md b/www/multitube/vendor/nikic/php-parser/CHANGELOG.md new file mode 100644 index 0000000..c2d9533 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/CHANGELOG.md @@ -0,0 +1,422 @@ +Version 3.1.6-dev +----------------- + +Nothing yet. + +Version 3.1.5 (2018-02-28) +-------------------------- + +### Fixed + +* Fixed duplicate comment assignment in switch statements. (#469) +* Improve compatibility with PHP-Scoper. (#477) + +Version 3.1.4 (2018-01-25) +-------------------------- + +### Fixed + +* Fixed pretty printing of `-(-$x)` and `+(+$x)`. (#459) + +Version 3.1.3 (2017-12-26) +-------------------------- + +### Fixed + +* Improve compatibility with php-scoper, by supporting prefixed namespaces in + `NodeAbstract::getType()`. + +Version 3.1.2 (2017-11-04) +-------------------------- + +### Fixed + +* Comments on empty blocks are now preserved on a `Stmt\Nop` node. (#382) + +### Added + +* Added `kind` attribute for `Stmt\Namespace_` node, which is one of `KIND_SEMICOLON` or + `KIND_BRACED`. (#417) +* Added `setDocComment()` method to namespace builder. (#437) + +Version 3.1.1 (2017-09-02) +-------------------------- + +### Fixed + +* Fixed syntax error on comment after brace-style namespace declaration. (#412) +* Added support for TraitUse statements in trait builder. (#413) + +Version 3.1.0 (2017-07-28) +-------------------------- + +### Added + +* [PHP 7.2] Added support for trailing comma in group use statements. +* [PHP 7.2] Added support for `object` type. This means `object` types will now be represented as a + builtin type (a simple `"object"` string), rather than a class `Name`. + +### Fixed + +* Floating-point numbers are now printed correctly if the LC_NUMERIC locale uses a comma as decimal + separator. + +### Changed + +* `Name::$parts` is no longer deprecated. + +Version 3.0.6 (2017-06-28) +-------------------------- + +### Fixed + +* Fixed the spelling of `Class_::VISIBILITY_MODIFIER_MASK`. The previous spelling of + `Class_::VISIBILITY_MODIFER_MASK` is preserved for backwards compatibility. +* The pretty printing will now preserve comments inside array literals and function calls by + printing the array items / function arguments on separate lines. Array literals and functions that + do not contain comments are not affected. + +### Added + +* Added `Builder\Param::makeVariadic()`. + +### Deprecated + +* The `Node::setLine()` method has been deprecated. + +Version 3.0.5 (2017-03-05) +-------------------------- + +### Fixed + +* Name resolution of `NullableType`s is now performed earlier, so that a fully resolved signature is + available when a function is entered. (#360) +* `Error` nodes are now considered empty, while previously they extended until the token where the + error occurred. This made some nodes larger than expected. (#359) +* Fixed notices being thrown during error recovery in some situations. (#362) + +Version 3.0.4 (2017-02-10) +-------------------------- + +### Fixed + +* Fixed some extensibility issues in pretty printer (`pUseType()` is now public and `pPrec()` calls + into `p()`, instead of directly dispatching to the type-specific printing method). +* Fixed notice in `bin/php-parse` script. + +### Added + +* Error recovery from missing semicolons is now supported in more cases. +* Error recovery from trailing commas in positions where PHP does not support them is now supported. + +Version 3.0.3 (2017-02-03) +-------------------------- + +### Fixed + +* In `"$foo[0]"` the `0` is now parsed as an `LNumber` rather than `String`. (#325) +* Ensure integers and floats are always pretty printed preserving semantics, even if the particular + value can only be manually constructed. +* Throw a `LogicException` when trying to pretty-print an `Error` node. Previously this resulted in + an undefined method exception or fatal error. + +### Added + +* [PHP 7.1] Added support for negative interpolated offsets: `"$foo[-1]"` +* Added `preserveOriginalNames` option to `NameResolver`. If this option is enabled, an + `originalName` attribute, containing the unresolved name, will be added to each resolved name. +* Added `php-parse --with-positions` option, which dumps nodes with position information. + +### Deprecated + +* The XML serializer has been deprecated. In particular, the classes `Serializer\XML`, + `Unserializer\XML`, as well as the interfaces `Serializer` and `Unserializer` are deprecated. + +Version 3.0.2 (2016-12-06) +-------------------------- + +### Fixed + +* Fixed name resolution of nullable types. (#324) +* Fixed pretty-printing of nullable types. + +Version 3.0.1 (2016-12-01) +-------------------------- + +### Fixed + +* Fixed handling of nested `list()`s: If the nested list was unkeyed, it was directly included in + the list items. If it was keyed, it was wrapped in `ArrayItem`. Now nested `List_` nodes are + always wrapped in `ArrayItem`s. (#321) + +Version 3.0.0 (2016-11-30) +-------------------------- + +### Added + +* Added support for dumping node positions in the NodeDumper through the `dumpPositions` option. +* Added error recovery support for `$`, `new`, `Foo::`. + +Version 3.0.0-beta2 (2016-10-29) +-------------------------------- + +This release primarily improves our support for error recovery. + +### Added + +* Added `Node::setDocComment()` method. +* Added `Error::getMessageWithColumnInfo()` method. +* Added support for recovery from lexer errors. +* Added support for recovering from "special" errors (i.e. non-syntax parse errors). +* Added precise location information for lexer errors. +* Added `ErrorHandler` interface, and `ErrorHandler\Throwing` and `ErrorHandler\Collecting` as + specific implementations. These provide a general mechanism for handling error recovery. +* Added optional `ErrorHandler` argument to `Parser::parse()`, `Lexer::startLexing()` and + `NameResolver::__construct()`. +* The `NameResolver` now adds a `namespacedName` attribute on name nodes that cannot be statically + resolved (unqualified unaliased function or constant names in namespaces). + +### Fixed + +* Fixed attribute assignment for `GroupUse` prefix and variables in interpolated strings. + +### Changed + +* The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class. +* Due to the error handling changes, the `Parser` interface and `Lexer` API have changed. +* The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences. + This changes the protected API of the lexer. +* The `Name::slice()` method now returns `null` for empty slices, previously `new Name([])` was + used. `Name::concat()` now also supports concatenation with `null`. + +### Removed + +* Removed `Name::append()` and `Name::prepend()`. These mutable methods have been superseded by + the immutable `Name::concat()`. +* Removed `Error::getRawLine()` and `Error::setRawLine()`. These methods have been superseded by + `Error::getStartLine()` and `Error::setStartLine()`. +* Removed support for node cloning in the `NodeTraverser`. +* Removed `$separator` argument from `Name::toString()`. +* Removed `throw_on_error` parser option and `Parser::getErrors()` method. Use the `ErrorHandler` + mechanism instead. + +Version 3.0.0-beta1 (2016-09-16) +-------------------------------- + +### Added + +* [7.1] Function/method and parameter builders now support PHP 7.1 type hints (void, iterable and + nullable types). +* Nodes and Comments now implement `JsonSerializable`. The node kind is stored in a `nodeType` + property. +* The `InlineHTML` node now has an `hasLeadingNewline` attribute, that specifies whether the + preceding closing tag contained a newline. The pretty printer honors this attribute. +* Partial parsing of `$obj->` (with missing property name) is now supported in error recovery mode. +* The error recovery mode is now exposed in the `php-parse` script through the `--with-recovery` + or `-r` flags. + +The following changes are also part of PHP-Parser 2.1.1: + +* The PHP 7 parser will now generate a parse error for `$var =& new Obj` assignments. +* Comments on free-standing code blocks will now be retained as comments on the first statement in + the code block. + +Version 3.0.0-alpha1 (2016-07-25) +--------------------------------- + +### Added + +* [7.1] Added support for `void` and `iterable` types. These will now be represented as strings + (instead of `Name` instances) similar to other builtin types. +* [7.1] Added support for class constant visibility. The `ClassConst` node now has a `flags` subnode + holding the visibility modifier, as well as `isPublic()`, `isProtected()` and `isPrivate()` + methods. The constructor changed to accept the additional subnode. +* [7.1] Added support for nullable types. These are represented using a new `NullableType` node + with a single `type` subnode. +* [7.1] Added support for short array destructuring syntax. This means that `Array` nodes may now + appear as the left-hand-side of assignments and foreach value targets. Additionally the array + items may now contain `null` values if elements are skipped. +* [7.1] Added support for keys in list() destructuring. The `List` subnode `vars` has been renamed + to `items` and now contains `ArrayItem`s instead of plain variables. +* [7.1] Added support for multi-catch. The `Catch` subnode `type` has been renamed to `types` and + is now an array of `Name`s. +* `Name::slice()` now supports lengths and negative offsets. This brings it in line with + `array_slice()` functionality. + +### Changed + +Due to PHP 7.1 support additions described above, the node structure changed as follows: + +* `void` and `iterable` types are now stored as strings if the PHP 7 parser is used. +* The `ClassConst` constructor changed to accept an additional `flags` subnode. +* The `Array` subnode `items` may now contain `null` elements (destructuring). +* The `List` subnode `vars` has been renamed to `items` and now contains `ArrayItem`s instead of + plain variables. +* The `Catch` subnode `type` has been renamed to `types` and is now an array of `Name`s. + +Additionally the following changes were made: + +* The `type` subnode on `Class`, `ClassMethod` and `Property` has been renamed to `flags`. The + `type` subnode has retained for backwards compatibility and is populated to the same value as + `flags`. However, writes to `type` will not update `flags`. +* The `TryCatch` subnode `finallyStmts` has been replaced with a `finally` subnode that holds an + explicit `Finally` node. This allows for more accurate attribute assignment. +* The `Trait` constructor now has the same form as the `Class` and `Interface` constructors: It + takes an array of subnodes. Unlike classes/interfaces, traits can only have a `stmts` subnode. +* The `NodeDumper` now prints class/method/property/constant modifiers, as well as the include and + use type in a textual representation, instead of only showing the number. +* All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public. + +### Removed + +* Removed support for running on PHP 5.4. It is however still possible to parse PHP 5.2-5.4 code + while running on a newer version. +* The deprecated `Comment::setLine()` and `Comment::setText()` methods have been removed. +* The deprecated `Name::set()`, `Name::setFirst()` and `Name::setLast()` methods have been removed. + +Version 2.1.1 (2016-09-16) +-------------------------- + +### Changed + +* The pretty printer will now escape all control characters in the range `\x00-\x1F` inside double + quoted strings. If no special escape sequence is available, an octal escape will be used. +* The quality of the error recovery has been improved. In particular unterminated expressions should + be handled more gracefully. +* The PHP 7 parser will now generate a parse error for `$var =& new Obj` assignments. +* Comments on free-standing code blocks will no be retained as comments on the first statement in + the code block. + +Version 2.1.0 (2016-04-19) +-------------------------- + +### Fixed + +* Properly support `B""` strings (with uppercase `B`) in a number of places. +* Fixed reformatting of indented parts in a certain non-standard comment style. + +### Added + +* Added `dumpComments` option to node dumper, to enable dumping of comments associated with nodes. +* Added `Stmt\Nop` node, that is used to collect comments located at the end of a block or at the + end of a file (without a following node with which they could otherwise be associated). +* Added `kind` attribute to `Expr\Exit` to distinguish between `exit` and `die`. +* Added `kind` attribute to `Scalar\LNumber` to distinguish between decimal, binary, octal and + hexadecimal numbers. +* Added `kind` attribtue to `Expr\Array` to distinguish between `array()` and `[]`. +* Added `kind` attribute to `Scalar\String` and `Scalar\Encapsed` to distinguish between + single-quoted, double-quoted, heredoc and nowdoc string. +* Added `docLabel` attribute to `Scalar\String` and `Scalar\Encapsed`, if it is a heredoc or + nowdoc string. +* Added start file offset information to `Comment` nodes. +* Added `setReturnType()` method to function and method builders. +* Added `-h` and `--help` options to `php-parse` script. + +### Changed + +* Invalid octal literals now throw a parse error in PHP 7 mode. +* The pretty printer takes all the new attributes mentioned in the previous section into account. +* The protected `AbstractPrettyPrinter::pComments()` method no longer returns a trailing newline. +* The bundled autoloader supports library files being stored in a different directory than + `PhpParser` for easier downstream distribution. + +### Deprecated + +* The `Comment::setLine()` and `Comment::setText()` methods have been deprecated. Construct new + objects instead. + +### Removed + +* The internal (but public) method `Scalar\LNumber::parse()` has been removed. A non-internal + `LNumber::fromString()` method has been added instead. + +Version 2.0.1 (2016-02-28) +-------------------------- + +### Fixed + +* `declare() {}` and `declare();` are not semantically equivalent and will now result in different + ASTs. The format case will have an empty `stmts` array, while the latter will set `stmts` to + `null`. +* Magic constants are now supported as semi-reserved keywords. +* A shebang line like `#!/usr/bin/env php` is now allowed at the start of a namespaced file. + Previously this generated an exception. +* The `prettyPrintFile()` method will not strip a trailing `?>` from the raw data that follows a + `__halt_compiler()` statement. +* The `prettyPrintFile()` method will not strip an opening `slice()` which takes a subslice of a name. + +### Changed + +* `PhpParser\Parser` is now an interface, implemented by `Parser\Php5`, `Parser\Php7` and + `Parser\Multiple`. The `Multiple` parser will try multiple parsers, until one succeeds. +* Token constants are now defined on `PhpParser\Parser\Tokens` rather than `PhpParser\Parser`. +* The `Name->set()`, `Name->append()`, `Name->prepend()` and `Name->setFirst()` methods are + deprecated in favor of `Name::concat()` and `Name->slice()`. +* The `NodeTraverser` no longer clones nodes by default. The old behavior can be restored by + passing `true` to the constructor. +* The constructor for `Scalar` nodes no longer has a default value. E.g. `new LNumber()` should now + be written as `new LNumber(0)`. + +--- + +**This changelog only includes changes from the 2.0 series. For older changes see the +[1.x series changelog](https://github.com/nikic/PHP-Parser/blob/1.x/CHANGELOG.md) and the +[0.9 series changelog](https://github.com/nikic/PHP-Parser/blob/0.9/CHANGELOG.md).** \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/LICENSE b/www/multitube/vendor/nikic/php-parser/LICENSE new file mode 100644 index 0000000..920cc5b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/LICENSE @@ -0,0 +1,31 @@ +Copyright (c) 2011-2018 by Nikita Popov. + +Some rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * The names of the contributors may not be used to endorse or + promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/www/multitube/vendor/nikic/php-parser/README.md b/www/multitube/vendor/nikic/php-parser/README.md new file mode 100644 index 0000000..2f62754 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/README.md @@ -0,0 +1,99 @@ +PHP Parser +========== + +[![Build Status](https://travis-ci.org/nikic/PHP-Parser.svg?branch=master)](https://travis-ci.org/nikic/PHP-Parser) [![Coverage Status](https://coveralls.io/repos/github/nikic/PHP-Parser/badge.svg?branch=master)](https://coveralls.io/github/nikic/PHP-Parser?branch=master) + +This is a PHP 5.2 to PHP 7.1 parser written in PHP. Its purpose is to simplify static code analysis and +manipulation. + +[**Documentation for version 3.x**][doc_master] (stable; for running on PHP >= 5.5; for parsing PHP 5.2 to PHP 7.1). + +[Documentation for version 2.x][doc_2_x] (stable; for running on PHP >= 5.4; for parsing PHP 5.2 to PHP 7.0). + +[Documentation for version 1.x][doc_1_x] (unsupported; for running on PHP >= 5.3; for parsing PHP 5.2 to PHP 5.6). + +In a Nutshell +------------- + +The parser turns PHP source code into an abstract syntax tree. For example, if you pass the following code into the +parser: + +```php + Expr_AssignOp_BitwiseAnd +Expr_AssignBitwiseOr => Expr_AssignOp_BitwiseOr +Expr_AssignBitwiseXor => Expr_AssignOp_BitwiseXor +Expr_AssignConcat => Expr_AssignOp_Concat +Expr_AssignDiv => Expr_AssignOp_Div +Expr_AssignMinus => Expr_AssignOp_Minus +Expr_AssignMod => Expr_AssignOp_Mod +Expr_AssignMul => Expr_AssignOp_Mul +Expr_AssignPlus => Expr_AssignOp_Plus +Expr_AssignShiftLeft => Expr_AssignOp_ShiftLeft +Expr_AssignShiftRight => Expr_AssignOp_ShiftRight + +Expr_BitwiseAnd => Expr_BinaryOp_BitwiseAnd +Expr_BitwiseOr => Expr_BinaryOp_BitwiseOr +Expr_BitwiseXor => Expr_BinaryOp_BitwiseXor +Expr_BooleanAnd => Expr_BinaryOp_BooleanAnd +Expr_BooleanOr => Expr_BinaryOp_BooleanOr +Expr_Concat => Expr_BinaryOp_Concat +Expr_Div => Expr_BinaryOp_Div +Expr_Equal => Expr_BinaryOp_Equal +Expr_Greater => Expr_BinaryOp_Greater +Expr_GreaterOrEqual => Expr_BinaryOp_GreaterOrEqual +Expr_Identical => Expr_BinaryOp_Identical +Expr_LogicalAnd => Expr_BinaryOp_LogicalAnd +Expr_LogicalOr => Expr_BinaryOp_LogicalOr +Expr_LogicalXor => Expr_BinaryOp_LogicalXor +Expr_Minus => Expr_BinaryOp_Minus +Expr_Mod => Expr_BinaryOp_Mod +Expr_Mul => Expr_BinaryOp_Mul +Expr_NotEqual => Expr_BinaryOp_NotEqual +Expr_NotIdentical => Expr_BinaryOp_NotIdentical +Expr_Plus => Expr_BinaryOp_Plus +Expr_ShiftLeft => Expr_BinaryOp_ShiftLeft +Expr_ShiftRight => Expr_BinaryOp_ShiftRight +Expr_Smaller => Expr_BinaryOp_Smaller +Expr_SmallerOrEqual => Expr_BinaryOp_SmallerOrEqual + +Scalar_ClassConst => Scalar_MagicConst_Class +Scalar_DirConst => Scalar_MagicConst_Dir +Scalar_FileConst => Scalar_MagicConst_File +Scalar_FuncConst => Scalar_MagicConst_Function +Scalar_LineConst => Scalar_MagicConst_Line +Scalar_MethodConst => Scalar_MagicConst_Method +Scalar_NSConst => Scalar_MagicConst_Namespace +Scalar_TraitConst => Scalar_MagicConst_Trait +``` + +These changes may affect custom pretty printers and code comparing the return value of `Node::getType()` to specific +strings. + +### Miscellaneous + + * The classes `Template` and `TemplateLoader` have been removed. You should use some other [code generation][code_gen] + project built on top of PHP-Parser instead. + + * The `PrettyPrinterAbstract::pStmts()` method now emits a leading newline if the statement list is not empty. + Custom pretty printers should remove the explicit newline before `pStmts()` calls. + + Old: + + ```php + public function pStmt_Trait(PHPParser_Node_Stmt_Trait $node) { + return 'trait ' . $node->name + . "\n" . '{' . "\n" . $this->pStmts($node->stmts) . "\n" . '}'; + } + ``` + + New: + + ```php + public function pStmt_Trait(Stmt\Trait_ $node) { + return 'trait ' . $node->name + . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; + } + ``` + + [code_gen]: https://github.com/nikic/PHP-Parser/wiki/Projects-using-the-PHP-Parser#code-generation \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/UPGRADE-2.0.md b/www/multitube/vendor/nikic/php-parser/UPGRADE-2.0.md new file mode 100644 index 0000000..1c61de5 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/UPGRADE-2.0.md @@ -0,0 +1,74 @@ +Upgrading from PHP-Parser 1.x to 2.0 +==================================== + +### PHP version requirements + +PHP-Parser now requires PHP 5.4 or newer to run. It is however still possible to *parse* PHP 5.2 and +PHP 5.3 source code, while running on a newer version. + +### Creating a parser instance + +Parser instances should now be created through the `ParserFactory`. Old direct instantiation code +will not work, because the parser class was renamed. + +Old: + +```php +use PhpParser\Parser, PhpParser\Lexer; +$parser = new Parser(new Lexer\Emulative); +``` + +New: + +```php +use PhpParser\ParserFactory; +$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); +``` + +The first argument to `ParserFactory` determines how different PHP versions are handled. The +possible values are: + + * `ParserFactory::PREFER_PHP7`: Try to parse code as PHP 7. If this fails, try to parse it as PHP 5. + * `ParserFactory::PREFER_PHP5`: Try to parse code as PHP 5. If this fails, try to parse it as PHP 7. + * `ParserFactory::ONLY_PHP7`: Parse code as PHP 7. + * `ParserFactory::ONLY_PHP5`: Parse code as PHP 5. + +For most practical purposes the difference between `PREFER_PHP7` and `PREFER_PHP5` is mainly whether +a scalar type hint like `string` will be stored as `'string'` (PHP 7) or as `new Name('string')` +(PHP 5). + +To use a custom lexer, pass it as the second argument to the `create()` method: + +```php +use PhpParser\ParserFactory; +$lexer = new MyLexer; +$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7, $lexer); +``` + +### Rename of the `PhpParser\Parser` class + +`PhpParser\Parser` is now an interface, which is implemented by `Parser\Php5`, `Parser\Php7` and +`Parser\Multiple`. Parser tokens are now defined in `Parser\Tokens`. If you use the `ParserFactory` +described above to create your parser instance, these changes should have no further impact on you. + +### Removal of legacy aliases + +All legacy aliases for classes have been removed. This includes the old non-namespaced `PHPParser_` +classes, as well as the classes that had to be renamed for PHP 7 support. + +### Deprecations + +The `set()`, `setFirst()`, `append()` and `prepend()` methods of the `Node\Name` class have been +deprecated. Instead `Name::concat()` and `Name->slice()` should be used. + +### Miscellaneous + +* The `NodeTraverser` no longer clones nodes by default. If you want to restore the old behavior, + pass `true` to the constructor. +* The legacy node format has been removed. If you use custom nodes, they are now expected to + implement a `getSubNodeNames()` method. +* The default value for `Scalar` node constructors was removed. This means that something like + `new LNumber()` should be replaced by `new LNumber(0)`. +* String parts of encapsed strings are now represented using `Scalar\EncapsStringPart` nodes, while + previously raw strings were used. This affects the `parts` child of `Scalar\Encaps` and + `Expr\ShellExec`. \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/UPGRADE-3.0.md b/www/multitube/vendor/nikic/php-parser/UPGRADE-3.0.md new file mode 100644 index 0000000..9e04f2a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/UPGRADE-3.0.md @@ -0,0 +1,160 @@ +Upgrading from PHP-Parser 2.x to 3.0 +==================================== + +The backwards-incompatible changes in this release may be summarized as follows: + + * The specific details of the node representation have changed in some cases, primarily to + accomodate new PHP 7.1 features. + * There have been significant changes to the error recovery implementation. This may affect you, + if you used the error recovery mode or have a custom lexer implementation. + * A number of deprecated methods were removed. + +### PHP version requirements + +PHP-Parser now requires PHP 5.5 or newer to run. It is however still possible to *parse* PHP 5.2, +5.3 and 5.4 source code, while running on a newer version. + +### Changes to the node structure + +The following changes are likely to require code changes if the respective nodes are used: + + * The `List` subnode `vars` has been renamed to `items` and now contains `ArrayItem`s instead of + plain variables. + * The `Catch` subnode `type` has been renamed to `types` and is now an array of `Name`s. + * The `TryCatch` subnode `finallyStmts` has been replaced with a `finally` subnode that holds an + explicit `Finally` node. + * The `type` subnode on `Class`, `ClassMethod` and `Property` has been renamed to `flags`. The + `type` subnode has retained for backwards compatibility and is populated to the same value as + `flags`. However, writes to `type` will not update `flags` and use of `type` is discouraged. + +The following changes are unlikely to require code changes: + + * The `ClassConst` constructor changed to accept an additional `flags` subnode. + * The `Trait` constructor now has the same form as the `Class` and `Interface` constructors: It + takes an array of subnodes. Unlike classes/interfaces, traits can only have a `stmts` subnode. + * The `Array` subnode `items` may now contain `null` elements (due to destructuring). + * `void` and `iterable` types are now stored as strings if the PHP 7 parser is used. Previously + these would have been represented as `Name` instances. + +### Changes to error recovery mode + +Previously, error recovery mode was enabled by setting the `throwOnError` option to `false` when +creating the parser, while collected errors were retrieved using the `getErrors()` method: + +```php +$lexer = ...; +$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer, [ + 'throwOnError' => true, +]); + +$stmts = $parser->parse($code); +$errors = $parser->getErrors(); +if ($errors) { + handleErrors($errors); +} +processAst($stmts); +``` + +Both the `throwOnError` option and the `getErrors()` method have been removed in PHP-Parser 3.0. +Instead an instance of `ErrorHandler\Collecting` should be passed to the `parse()` method: + +```php +$lexer = ...; +$parser = (new ParserFactory)->create(ParserFactor::ONLY_PHP7, $lexer); + +$errorHandler = new ErrorHandler\Collecting; +$stmts = $parser->parse($code, $errorHandler); +if ($errorHandler->hasErrors()) { + handleErrors($errorHandler->getErrors()); +} +processAst($stmts); +``` + +#### Multiple parser fallback in error recovery mode + +As a result of this change, if a `Multiple` parser is used (e.g. through the `ParserFactory` using +`PREFER_PHP7` or `PREFER_PHP5`), it will now return the result of the first *non-throwing* parse. As +parsing never throws in error recovery mode, the result from the first parser will always be +returned. + +The PHP 7 parser is a superset of the PHP 5 parser, with the exceptions that `=& new` and +`global $$foo->bar` are not supported (other differences are in representation only). The PHP 7 +parser will be able to recover from the error in both cases. For this reason, this change will +likely pass unnoticed if you do not specifically test for this syntax. + +It is possible to restore the precise previous behavior with the following code: + +```php +$lexer = ...; +$parser7 = new Parser\Php7($lexer); +$parser5 = new Parser\Php5($lexer); + +$errors7 = new ErrorHandler\Collecting(); +$stmts7 = $parser7->parse($code, $errors7); +if ($errors7->hasErrors()) { + $errors5 = new ErrorHandler\Collecting(); + $stmts5 = $parser5->parse($code, $errors5); + if (!$errors5->hasErrors()) { + // If PHP 7 parse has errors but PHP 5 parse has no errors, use PHP 5 result + return [$stmts5, $errors5]; + } +} +// If PHP 7 succeeds or both fail use PHP 7 result +return [$stmts7, $errors7]; +``` + +#### Error handling in the lexer + +In order to support recovery from lexer errors, the signature of the `startLexing()` method changed +to optionally accept an `ErrorHandler`: + +```php +// OLD +public function startLexing($code); +// NEW +public function startLexing($code, ErrorHandler $errorHandler = null); +``` + +If you use a custom lexer with overriden `startLexing()` method, it needs to be changed to accept +the extra parameter. The value should be passed on to the parent method. + +#### Error checks in node constructors + +The constructors of certain nodes used to contain additional checks for semantic errors, such as +creating a try block without either catch or finally. These checks have been moved from the node +constructors into the parser. This allows recovery from such errors, as well as representing the +resulting (invalid) AST. + +This means that certain error conditions are no longer checked for manually constructed nodes. + +### Removed methods, arguments, options + +The following methods, arguments or options have been removed: + + * `Comment::setLine()`, `Comment::setText()`: Create new `Comment` instances instead. + * `Name::set()`, `Name::setFirst()`, `Name::setLast()`, `Name::append()`, `Name::prepend()`: + Use `Name::concat()` in combination with `Name::slice()` instead. + * `Error::getRawLine()`, `Error::setRawLine()`. Use `Error::getStartLine()` and + `Error::setStartLine()` instead. + * `Parser::getErrors()`. Use `ErrorHandler\Collecting` instead. + * `$separator` argument of `Name::toString()`. Use `strtr()` instead, if you really need it. + * `$cloneNodes` argument of `NodeTraverser::__construct()`. Explicitly clone nodes in the visitor + instead. + * `throwOnError` parser option. Use `ErrorHandler\Collecting` instead. + +### Miscellaneous + + * The `NameResolver` will now resolve unqualified function and constant names in the global + namespace into fully qualified names. For example `foo()` in the global namespace resolves to + `\foo()`. For names where no static resolution is possible, a `namespacedName` attribute is + added now, containing the namespaced variant of the name. + * All methods on `PrettyPrinter\Standard` are now protected. Previoulsy most of them were public. + The pretty printer should only be invoked using the `prettyPrint()`, `prettyPrintFile()` and + `prettyPrintExpr()` methods. + * The node dumper now prints numeric values that act as enums/flags in a string representation. + If node dumper results are used in tests, updates may be needed to account for this. + * The constants on `NameTraverserInterface` have been moved into the `NameTraverser` class. + * The emulative lexer now directly postprocesses tokens, instead of using `~__EMU__~` sequences. + This changes the protected API of the emulative lexer. + * The `Name::slice()` method now returns `null` for empty slices, previously `new Name([])` was + used. `Name::concat()` now also supports concatenation with `null`. diff --git a/www/multitube/vendor/nikic/php-parser/bin/php-parse b/www/multitube/vendor/nikic/php-parser/bin/php-parse new file mode 100755 index 0000000..1760e75 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/bin/php-parse @@ -0,0 +1,202 @@ +#!/usr/bin/env php + array( + 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' +))); +$parser = (new PhpParser\ParserFactory)->create( + PhpParser\ParserFactory::PREFER_PHP7, + $lexer +); +$dumper = new PhpParser\NodeDumper([ + 'dumpComments' => true, + 'dumpPositions' => $attributes['with-positions'], +]); +$prettyPrinter = new PhpParser\PrettyPrinter\Standard; +$serializer = new PhpParser\Serializer\XML; + +$traverser = new PhpParser\NodeTraverser(); +$traverser->addVisitor(new PhpParser\NodeVisitor\NameResolver); + +foreach ($files as $file) { + if (strpos($file, ' Code $code\n"; + } else { + if (!file_exists($file)) { + die("File $file does not exist.\n"); + } + + $code = file_get_contents($file); + echo "====> File $file:\n"; + } + + if ($attributes['with-recovery']) { + $errorHandler = new PhpParser\ErrorHandler\Collecting; + $stmts = $parser->parse($code, $errorHandler); + foreach ($errorHandler->getErrors() as $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + echo $message . "\n"; + } + if (null === $stmts) { + continue; + } + } else { + try { + $stmts = $parser->parse($code); + } catch (PhpParser\Error $error) { + $message = formatErrorMessage($error, $code, $attributes['with-column-info']); + die($message . "\n"); + } + } + + foreach ($operations as $operation) { + if ('dump' === $operation) { + echo "==> Node dump:\n"; + echo $dumper->dump($stmts, $code), "\n"; + } elseif ('pretty-print' === $operation) { + echo "==> Pretty print:\n"; + echo $prettyPrinter->prettyPrintFile($stmts), "\n"; + } elseif ('serialize-xml' === $operation) { + echo "==> Serialized XML:\n"; + echo $serializer->serialize($stmts), "\n"; + } elseif ('var-dump' === $operation) { + echo "==> var_dump():\n"; + var_dump($stmts); + } elseif ('resolve-names' === $operation) { + echo "==> Resolved names.\n"; + $stmts = $traverser->traverse($stmts); + } + } +} + +function formatErrorMessage(PhpParser\Error $e, $code, $withColumnInfo) { + if ($withColumnInfo && $e->hasColumnInfo()) { + return $e->getMessageWithColumnInfo($code); + } else { + return $e->getMessage(); + } +} + +function showHelp($error = '') { + if ($error) { + echo $error . "\n\n"; + } + die(<< false, + 'with-positions' => false, + 'with-recovery' => false, + ); + + array_shift($args); + $parseOptions = true; + foreach ($args as $arg) { + if (!$parseOptions) { + $files[] = $arg; + continue; + } + + switch ($arg) { + case '--dump': + case '-d': + $operations[] = 'dump'; + break; + case '--pretty-print': + case '-p': + $operations[] = 'pretty-print'; + break; + case '--serialize-xml': + $operations[] = 'serialize-xml'; + break; + case '--var-dump': + $operations[] = 'var-dump'; + break; + case '--resolve-names': + case '-N'; + $operations[] = 'resolve-names'; + break; + case '--with-column-info': + case '-c'; + $attributes['with-column-info'] = true; + break; + case '--with-positions': + case '-P': + $attributes['with-positions'] = true; + break; + case '--with-recovery': + case '-r': + $attributes['with-recovery'] = true; + break; + case '--help': + case '-h'; + showHelp(); + break; + case '--': + $parseOptions = false; + break; + default: + if ($arg[0] === '-') { + showHelp("Invalid operation $arg."); + } else { + $files[] = $arg; + } + } + } + + return array($operations, $files, $attributes); +} diff --git a/www/multitube/vendor/nikic/php-parser/composer.json b/www/multitube/vendor/nikic/php-parser/composer.json new file mode 100644 index 0000000..66df90a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/composer.json @@ -0,0 +1,30 @@ +{ + "name": "nikic/php-parser", + "description": "A PHP parser written in PHP", + "keywords": ["php", "parser"], + "type": "library", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Nikita Popov" + } + ], + "require": { + "php": ">=5.5", + "ext-tokenizer": "*" + }, + "require-dev": { + "phpunit/phpunit": "~4.0|~5.0" + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "bin": ["bin/php-parse"], + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/doc/0_Introduction.markdown b/www/multitube/vendor/nikic/php-parser/doc/0_Introduction.markdown new file mode 100644 index 0000000..ca1ceb2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/doc/0_Introduction.markdown @@ -0,0 +1,80 @@ +Introduction +============ + +This project is a PHP 5.2 to PHP 7.1 parser **written in PHP itself**. + +What is this for? +----------------- + +A parser is useful for [static analysis][0], manipulation of code and basically any other +application dealing with code programmatically. A parser constructs an [Abstract Syntax Tree][1] +(AST) of the code and thus allows dealing with it in an abstract and robust way. + +There are other ways of processing source code. One that PHP supports natively is using the +token stream generated by [`token_get_all`][2]. The token stream is much more low level than +the AST and thus has different applications: It allows to also analyze the exact formatting of +a file. On the other hand the token stream is much harder to deal with for more complex analysis. +For example an AST abstracts away the fact that in PHP variables can be written as `$foo`, but also +as `$$bar`, `${'foobar'}` or even `${!${''}=barfoo()}`. You don't have to worry about recognizing +all the different syntaxes from a stream of tokens. + +Another question is: Why would I want to have a PHP parser *written in PHP*? Well, PHP might not be +a language especially suited for fast parsing, but processing the AST is much easier in PHP than it +would be in other, faster languages like C. Furthermore the people most probably wanting to do +programmatic PHP code analysis are incidentally PHP developers, not C developers. + +What can it parse? +------------------ + +The parser supports parsing PHP 5.2-5.6 and PHP 7. + +As the parser is based on the tokens returned by `token_get_all` (which is only able to lex the PHP +version it runs on), additionally a wrapper for emulating tokens from newer versions is provided. +This allows to parse PHP 7.1 source code running on PHP 5.5, for example. This emulation is somewhat +hacky and not perfect, but it should work well on any sane code. + +What output does it produce? +---------------------------- + +The parser produces an [Abstract Syntax Tree][1] (AST) also known as a node tree. How this looks like +can best be seen in an example. The program `create(ParserFactory::PREFER_PHP7); +``` + +The factory accepts a kind argument, that determines how different PHP versions are treated: + +Kind | Behavior +-----|--------- +`ParserFactory::PREFER_PHP7` | Try to parse code as PHP 7. If this fails, try to parse it as PHP 5. +`ParserFactory::PREFER_PHP5` | Try to parse code as PHP 5. If this fails, try to parse it as PHP 7. +`ParserFactory::ONLY_PHP7` | Parse code as PHP 7. +`ParserFactory::ONLY_PHP5` | Parse code as PHP 5. + +Unless you have strong reason to use something else, `PREFER_PHP7` is a reasonable default. + +The `create()` method optionally accepts a `Lexer` instance as the second argument. Some use cases +that require customized lexers are discussed in the [lexer documentation](component/Lexer.markdown). + +Subsequently you can pass PHP code (including the opening `create(ParserFactory::PREFER_PHP7); + +try { + $stmts = $parser->parse($code); + // $stmts is an array of statement nodes +} catch (Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +A parser instance can be reused to parse multiple files. + +Node tree +--------- + +If you use the above code with `$code = "subNodeName`. The `Stmt\Echo_` node has only one subnode `exprs`. So in order to access it +in the above example you would write `$stmts[0]->exprs`. If you wanted to access the name of the function +call, you would write `$stmts[0]->exprs[1]->name`. + +All nodes also define a `getType()` method that returns the node type. The type is the class name +without the `PhpParser\Node\` prefix and `\` replaced with `_`. It also does not contain a trailing +`_` for reserved-keyword class names. + +It is possible to associate custom metadata with a node using the `setAttribute()` method. This data +can then be retrieved using `hasAttribute()`, `getAttribute()` and `getAttributes()`. + +By default the lexer adds the `startLine`, `endLine` and `comments` attributes. `comments` is an array +of `PhpParser\Comment[\Doc]` instances. + +The start line can also be accessed using `getLine()`/`setLine()` (instead of `getAttribute('startLine')`). +The last doc comment from the `comments` attribute can be obtained using `getDocComment()`. + +Pretty printer +-------------- + +The pretty printer component compiles the AST back to PHP code. As the parser does not retain formatting +information the formatting is done using a specified scheme. Currently there is only one scheme available, +namely `PhpParser\PrettyPrinter\Standard`. + +```php +use PhpParser\Error; +use PhpParser\ParserFactory; +use PhpParser\PrettyPrinter; + +$code = "create(ParserFactory::PREFER_PHP7); +$prettyPrinter = new PrettyPrinter\Standard; + +try { + // parse + $stmts = $parser->parse($code); + + // change + $stmts[0] // the echo statement + ->exprs // sub expressions + [0] // the first of them (the string node) + ->value // it's value, i.e. 'Hi ' + = 'Hello '; // change to 'Hello ' + + // pretty print + $code = $prettyPrinter->prettyPrint($stmts); + + echo $code; +} catch (Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +The above code will output: + + parse()`, then changed and then +again converted to code using `PhpParser\PrettyPrinter\Standard->prettyPrint()`. + +The `prettyPrint()` method pretty prints a statements array. It is also possible to pretty print only a +single expression using `prettyPrintExpr()`. + +The `prettyPrintFile()` method can be used to print an entire file. This will include the opening `create(ParserFactory::PREFER_PHP7); +$traverser = new NodeTraverser; +$prettyPrinter = new PrettyPrinter\Standard; + +// add your visitor +$traverser->addVisitor(new MyNodeVisitor); + +try { + $code = file_get_contents($fileName); + + // parse + $stmts = $parser->parse($code); + + // traverse + $stmts = $traverser->traverse($stmts); + + // pretty print + $code = $prettyPrinter->prettyPrintFile($stmts); + + echo $code; +} catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +The corresponding node visitor might look like this: + +```php +use PhpParser\Node; +use PhpParser\NodeVisitorAbstract; + +class MyNodeVisitor extends NodeVisitorAbstract +{ + public function leaveNode(Node $node) { + if ($node instanceof Node\Scalar\String_) { + $node->value = 'foo'; + } + } +} +``` + +The above node visitor would change all string literals in the program to `'foo'`. + +All visitors must implement the `PhpParser\NodeVisitor` interface, which defines the following four +methods: + +```php +public function beforeTraverse(array $nodes); +public function enterNode(\PhpParser\Node $node); +public function leaveNode(\PhpParser\Node $node); +public function afterTraverse(array $nodes); +``` + +The `beforeTraverse()` method is called once before the traversal begins and is passed the nodes the +traverser was called with. This method can be used for resetting values before traversation or +preparing the tree for traversal. + +The `afterTraverse()` method is similar to the `beforeTraverse()` method, with the only difference that +it is called once after the traversal. + +The `enterNode()` and `leaveNode()` methods are called on every node, the former when it is entered, +i.e. before its subnodes are traversed, the latter when it is left. + +All four methods can either return the changed node or not return at all (i.e. `null`) in which +case the current node is not changed. + +The `enterNode()` method can additionally return the value `NodeTraverser::DONT_TRAVERSE_CHILDREN`, +which instructs the traverser to skip all children of the current node. + +The `leaveNode()` method can additionally return the value `NodeTraverser::REMOVE_NODE`, in which +case the current node will be removed from the parent array. Furthermore it is possible to return +an array of nodes, which will be merged into the parent array at the offset of the current node. +I.e. if in `array(A, B, C)` the node `B` should be replaced with `array(X, Y, Z)` the result will +be `array(A, X, Y, Z, C)`. + +Instead of manually implementing the `NodeVisitor` interface you can also extend the `NodeVisitorAbstract` +class, which will define empty default implementations for all the above methods. + +The NameResolver node visitor +----------------------------- + +One visitor is already bundled with the package: `PhpParser\NodeVisitor\NameResolver`. This visitor +helps you work with namespaced code by trying to resolve most names to fully qualified ones. + +For example, consider the following code: + + use A as B; + new B\C(); + +In order to know that `B\C` really is `A\C` you would need to track aliases and namespaces yourself. +The `NameResolver` takes care of that and resolves names as far as possible. + +After running it most names will be fully qualified. The only names that will stay unqualified are +unqualified function and constant names. These are resolved at runtime and thus the visitor can't +know which function they are referring to. In most cases this is a non-issue as the global functions +are meant. + +Also the `NameResolver` adds a `namespacedName` subnode to class, function and constant declarations +that contains the namespaced name instead of only the shortname that is available via `name`. + +Example: Converting namespaced code to pseudo namespaces +-------------------------------------------------------- + +A small example to understand the concept: We want to convert namespaced code to pseudo namespaces +so it works on 5.2, i.e. names like `A\\B` should be converted to `A_B`. Note that such conversions +are fairly complicated if you take PHP's dynamic features into account, so our conversion will +assume that no dynamic features are used. + +We start off with the following base code: + +```php +use PhpParser\ParserFactory; +use PhpParser\PrettyPrinter; +use PhpParser\NodeTraverser; +use PhpParser\NodeVisitor\NameResolver; + +$inDir = '/some/path'; +$outDir = '/some/other/path'; + +$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7); +$traverser = new NodeTraverser; +$prettyPrinter = new PrettyPrinter\Standard; + +$traverser->addVisitor(new NameResolver); // we will need resolved names +$traverser->addVisitor(new NamespaceConverter); // our own node visitor + +// iterate over all .php files in the directory +$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($inDir)); +$files = new \RegexIterator($files, '/\.php$/'); + +foreach ($files as $file) { + try { + // read the file that should be converted + $code = file_get_contents($file); + + // parse + $stmts = $parser->parse($code); + + // traverse + $stmts = $traverser->traverse($stmts); + + // pretty print + $code = $prettyPrinter->prettyPrintFile($stmts); + + // write the converted file to the target directory + file_put_contents( + substr_replace($file->getPathname(), $outDir, 0, strlen($inDir)), + $code + ); + } catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); + } +} +``` + +Now lets start with the main code, the `NodeVisitor\NamespaceConverter`. One thing it needs to do +is convert `A\\B` style names to `A_B` style ones. + +```php +use PhpParser\Node; + +class NamespaceConverter extends \PhpParser\NodeVisitorAbstract +{ + public function leaveNode(Node $node) { + if ($node instanceof Node\Name) { + return new Node\Name($node->toString('_')); + } + } +} +``` + +The above code profits from the fact that the `NameResolver` already resolved all names as far as +possible, so we don't need to do that. We only need to create a string with the name parts separated +by underscores instead of backslashes. This is what `$node->toString('_')` does. (If you want to +create a name with backslashes either write `$node->toString()` or `(string) $node`.) Then we create +a new name from the string and return it. Returning a new node replaces the old node. + +Another thing we need to do is change the class/function/const declarations. Currently they contain +only the shortname (i.e. the last part of the name), but they need to contain the complete name including +the namespace prefix: + +```php +use PhpParser\Node; +use PhpParser\Node\Stmt; + +class NodeVisitor_NamespaceConverter extends \PhpParser\NodeVisitorAbstract +{ + public function leaveNode(Node $node) { + if ($node instanceof Node\Name) { + return new Node\Name($node->toString('_')); + } elseif ($node instanceof Stmt\Class_ + || $node instanceof Stmt\Interface_ + || $node instanceof Stmt\Function_) { + $node->name = $node->namespacedName->toString('_'); + } elseif ($node instanceof Stmt\Const_) { + foreach ($node->consts as $const) { + $const->name = $const->namespacedName->toString('_'); + } + } + } +} +``` + +There is not much more to it than converting the namespaced name to string with `_` as separator. + +The last thing we need to do is remove the `namespace` and `use` statements: + +```php +use PhpParser\Node; +use PhpParser\Node\Stmt; + +class NodeVisitor_NamespaceConverter extends \PhpParser\NodeVisitorAbstract +{ + public function leaveNode(Node $node) { + if ($node instanceof Node\Name) { + return new Node\Name($node->toString('_')); + } elseif ($node instanceof Stmt\Class_ + || $node instanceof Stmt\Interface_ + || $node instanceof Stmt\Function_) { + $node->name = $node->namespacedName->toString('_'); + } elseif ($node instanceof Stmt\Const_) { + foreach ($node->consts as $const) { + $const->name = $const->namespacedName->toString('_'); + } + } elseif ($node instanceof Stmt\Namespace_) { + // returning an array merges is into the parent array + return $node->stmts; + } elseif ($node instanceof Stmt\Use_) { + // returning false removed the node altogether + return false; + } + } +} +``` + +That's all. diff --git a/www/multitube/vendor/nikic/php-parser/doc/3_Other_node_tree_representations.markdown b/www/multitube/vendor/nikic/php-parser/doc/3_Other_node_tree_representations.markdown new file mode 100644 index 0000000..0830f39 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/doc/3_Other_node_tree_representations.markdown @@ -0,0 +1,330 @@ +Other node tree representations +=============================== + +It is possible to convert the AST into several textual representations, which serve different uses. + +Simple serialization +-------------------- + +It is possible to serialize the node tree using `serialize()` and also unserialize it using +`unserialize()`. The output is not human readable and not easily processable from anything +but PHP, but it is compact and generates quickly. The main application thus is in caching. + +Human readable dumping +---------------------- + +Furthermore it is possible to dump nodes into a human readable format using the `dump` method of +`PhpParser\NodeDumper`. This can be used for debugging. + +```php +$code = <<<'CODE' +create(PhpParser\ParserFactory::PREFER_PHP7); +$nodeDumper = new PhpParser\NodeDumper; + +try { + $stmts = $parser->parse($code); + + echo $nodeDumper->dump($stmts), "\n"; +} catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +The above script will have an output looking roughly like this: + +``` +array( + 0: Stmt_Function( + byRef: false + params: array( + 0: Param( + name: msg + default: null + type: null + byRef: false + ) + ) + stmts: array( + 0: Stmt_Echo( + exprs: array( + 0: Expr_Variable( + name: msg + ) + 1: Scalar_String( + value: + + ) + ) + ) + ) + name: printLine + ) + 1: Expr_FuncCall( + name: Name( + parts: array( + 0: printLine + ) + ) + args: array( + 0: Arg( + value: Scalar_String( + value: Hello World!!! + ) + byRef: false + ) + ) + ) +) +``` + +JSON encoding +------------- + +Nodes (and comments) implement the `JsonSerializable` interface. As such, it is possible to JSON +encode the AST directly using `json_encode()`: + +```php +$code = <<<'CODE' +create(PhpParser\ParserFactory::PREFER_PHP7); +$nodeDumper = new PhpParser\NodeDumper; + +try { + $stmts = $parser->parse($code); + + echo json_encode($stmts, JSON_PRETTY_PRINT), "\n"; +} catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +This will result in the following output (which includes attributes): + +```json +[ + { + "nodeType": "Stmt_Function", + "byRef": false, + "name": "printLine", + "params": [ + { + "nodeType": "Param", + "type": null, + "byRef": false, + "variadic": false, + "name": "msg", + "default": null, + "attributes": { + "startLine": 3, + "endLine": 3 + } + } + ], + "returnType": null, + "stmts": [ + { + "nodeType": "Stmt_Echo", + "exprs": [ + { + "nodeType": "Expr_Variable", + "name": "msg", + "attributes": { + "startLine": 4, + "endLine": 4 + } + }, + { + "nodeType": "Scalar_String", + "value": "\n", + "attributes": { + "startLine": 4, + "endLine": 4, + "kind": 2 + } + } + ], + "attributes": { + "startLine": 4, + "endLine": 4 + } + } + ], + "attributes": { + "startLine": 3, + "endLine": 5 + } + }, + { + "nodeType": "Expr_FuncCall", + "name": { + "nodeType": "Name", + "parts": [ + "printLine" + ], + "attributes": { + "startLine": 7, + "endLine": 7 + } + }, + "args": [ + { + "nodeType": "Arg", + "value": { + "nodeType": "Scalar_String", + "value": "Hello World!!!", + "attributes": { + "startLine": 7, + "endLine": 7, + "kind": 1 + } + }, + "byRef": false, + "unpack": false, + "attributes": { + "startLine": 7, + "endLine": 7 + } + } + ], + "attributes": { + "startLine": 7, + "endLine": 7 + } + } +] +``` + +There is currently no mechanism to convert JSON back into a node tree. Furthermore, not all ASTs +can be JSON encoded. In particular, JSON only supports UTF-8 strings. + +Serialization to XML +-------------------- + +It is also possible to serialize the node tree to XML using `PhpParser\Serializer\XML->serialize()` +and to unserialize it using `PhpParser\Unserializer\XML->unserialize()`. This is useful for +interfacing with other languages and applications or for doing transformation using XSLT. + +```php +create(PhpParser\ParserFactory::PREFER_PHP7); +$serializer = new PhpParser\Serializer\XML; + +try { + $stmts = $parser->parse($code); + + echo $serializer->serialize($stmts); +} catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +Produces: + +```xml + + + + + + + + + + + + msg + + + + + + + + + + + + + + + + + + + + + msg + + + + + + + + + + + + + + + printLine + + + + + + + + printLine + + + + + + + + + + + Hello World!!! + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/doc/4_Code_generation.markdown b/www/multitube/vendor/nikic/php-parser/doc/4_Code_generation.markdown new file mode 100644 index 0000000..2c0aa0e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/doc/4_Code_generation.markdown @@ -0,0 +1,84 @@ +Code generation +=============== + +It is also possible to generate code using the parser, by first creating an Abstract Syntax Tree and then using the +pretty printer to convert it to PHP code. To simplify code generation, the project comes with builders which allow +creating node trees using a fluid interface, instead of instantiating all nodes manually. Builders are available for +the following syntactic elements: + + * namespaces and use statements + * classes, interfaces and traits + * methods, functions and parameters + * properties + +Here is an example: + +```php +use PhpParser\BuilderFactory; +use PhpParser\PrettyPrinter; +use PhpParser\Node; + +$factory = new BuilderFactory; +$node = $factory->namespace('Name\Space') + ->addStmt($factory->use('Some\Other\Thingy')->as('SomeOtherClass')) + ->addStmt($factory->class('SomeClass') + ->extend('SomeOtherClass') + ->implement('A\Few', '\Interfaces') + ->makeAbstract() // ->makeFinal() + + ->addStmt($factory->method('someMethod') + ->makePublic() + ->makeAbstract() // ->makeFinal() + ->setReturnType('bool') + ->addParam($factory->param('someParam')->setTypeHint('SomeClass')) + ->setDocComment('/** + * This method does something. + * + * @param SomeClass And takes a parameter + */') + ) + + ->addStmt($factory->method('anotherMethod') + ->makeProtected() // ->makePublic() [default], ->makePrivate() + ->addParam($factory->param('someParam')->setDefault('test')) + // it is possible to add manually created nodes + ->addStmt(new Node\Expr\Print_(new Node\Expr\Variable('someParam'))) + ) + + // properties will be correctly reordered above the methods + ->addStmt($factory->property('someProperty')->makeProtected()) + ->addStmt($factory->property('anotherProperty')->makePrivate()->setDefault(array(1, 2, 3))) + ) + + ->getNode() +; + +$stmts = array($node); +$prettyPrinter = new PrettyPrinter\Standard(); +echo $prettyPrinter->prettyPrintFile($stmts); +``` + +This will produce the following output with the standard pretty printer: + +```php + array('comments', 'startLine', 'endLine', 'startFilePos', 'endFilePos'), +)); +$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer); + +try { + $stmts = $parser->parse($code); + // ... +} catch (PhpParser\Error $e) { + // ... +} +``` + +Before using column information its availability needs to be checked with `$e->hasColumnInfo()`, as the precise +location of an error cannot always be determined. The methods for retrieving column information also have to be passed +the source code of the parsed file. An example for printing an error: + +```php +if ($e->hasColumnInfo()) { + echo $e->getRawMessage() . ' from ' . $e->getStartLine() . ':' . $e->getStartColumn($code) + . ' to ' . $e->getEndLine() . ':' . $e->getEndColumn($code); + // or: + echo $e->getMessageWithColumnInfo(); +} else { + echo $e->getMessage(); +} +``` + +Both line numbers and column numbers are 1-based. EOF errors will be located at the position one past the end of the +file. + +Error recovery +-------------- + +The error behavior of the parser (and other components) is controlled by an `ErrorHandler`. Whenever an error is +encountered, `ErrorHandler::handleError()` is invoked. The default error handling strategy is `ErrorHandler\Throwing`, +which will immediately throw when an error is encountered. + +To instead collect all encountered errors into an array, while trying to continue parsing the rest of the source code, +an instance of `ErrorHandler\Collecting` can be passed to the `Parser::parse()` method. A usage example: + +```php +$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::ONLY_PHP7); +$errorHandler = new PhpParser\ErrorHandler\Collecting; + +$stmts = $parser->parse($code, $errorHandler); + +if ($errorHandler->hasErrors()) { + foreach ($errorHandler->getErrors() as $error) { + // $error is an ordinary PhpParser\Error + } +} + +if (null !== $stmts) { + // $stmts is a best-effort partial AST +} +``` + +The `NameResolver` visitor also accepts an `ErrorHandler` as a constructor argument. \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/doc/component/Lexer.markdown b/www/multitube/vendor/nikic/php-parser/doc/component/Lexer.markdown new file mode 100644 index 0000000..b22942d --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/doc/component/Lexer.markdown @@ -0,0 +1,152 @@ +Lexer component documentation +============================= + +The lexer is responsible for providing tokens to the parser. The project comes with two lexers: `PhpParser\Lexer` and +`PhpParser\Lexer\Emulative`. The latter is an extension of the former, which adds the ability to emulate tokens of +newer PHP versions and thus allows parsing of new code on older versions. + +This documentation discusses options available for the default lexers and explains how lexers can be extended. + +Lexer options +------------- + +The two default lexers accept an `$options` array in the constructor. Currently only the `'usedAttributes'` option is +supported, which allows you to specify which attributes will be added to the AST nodes. The attributes can then be +accessed using `$node->getAttribute()`, `$node->setAttribute()`, `$node->hasAttribute()` and `$node->getAttributes()` +methods. A sample options array: + +```php +$lexer = new PhpParser\Lexer(array( + 'usedAttributes' => array( + 'comments', 'startLine', 'endLine' + ) +)); +``` + +The attributes used in this example match the default behavior of the lexer. The following attributes are supported: + + * `comments`: Array of `PhpParser\Comment` or `PhpParser\Comment\Doc` instances, representing all comments that occurred + between the previous non-discarded token and the current one. Use of this attribute is required for the + `$node->getDocComment()` method to work. The attribute is also needed if you wish the pretty printer to retain + comments present in the original code. + * `startLine`: Line in which the node starts. This attribute is required for the `$node->getLine()` to work. It is also + required if syntax errors should contain line number information. + * `endLine`: Line in which the node ends. + * `startTokenPos`: Offset into the token array of the first token in the node. + * `endTokenPos`: Offset into the token array of the last token in the node. + * `startFilePos`: Offset into the code string of the first character that is part of the node. + * `endFilePos`: Offset into the code string of the last character that is part of the node. + +### Using token positions + +The token offset information is useful if you wish to examine the exact formatting used for a node. For example the AST +does not distinguish whether a property was declared using `public` or using `var`, but you can retrieve this +information based on the token position: + +```php +function isDeclaredUsingVar(array $tokens, PhpParser\Node\Stmt\Property $prop) { + $i = $prop->getAttribute('startTokenPos'); + return $tokens[$i][0] === T_VAR; +} +``` + +In order to make use of this function, you will have to provide the tokens from the lexer to your node visitor using +code similar to the following: + +```php +class MyNodeVisitor extends PhpParser\NodeVisitorAbstract { + private $tokens; + public function setTokens(array $tokens) { + $this->tokens = $tokens; + } + + public function leaveNode(PhpParser\Node $node) { + if ($node instanceof PhpParser\Node\Stmt\Property) { + var_dump(isDeclaredUsingVar($this->tokens, $node)); + } + } +} + +$lexer = new PhpParser\Lexer(array( + 'usedAttributes' => array( + 'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos' + ) +)); +$parser = (new PhpParser\ParserFactory)->create(PhpParser\ParserFactory::PREFER_PHP7, $lexer); + +$visitor = new MyNodeVisitor(); +$traverser = new PhpParser\NodeTraverser(); +$traverser->addVisitor($visitor); + +try { + $stmts = $parser->parse($code); + $visitor->setTokens($lexer->getTokens()); + $stmts = $traverser->traverse($stmts); +} catch (PhpParser\Error $e) { + echo 'Parse Error: ', $e->getMessage(); +} +``` + +The same approach can also be used to perform specific modifications in the code, without changing the formatting in +other places (which is the case when using the pretty printer). + +Lexer extension +--------------- + +A lexer has to define the following public interface: + + void startLexing(string $code, ErrorHandler $errorHandler = null); + array getTokens(); + string handleHaltCompiler(); + int getNextToken(string &$value = null, array &$startAttributes = null, array &$endAttributes = null); + +The `startLexing()` method is invoked with the source code that is to be lexed (including the opening tag) whenever the +`parse()` method of the parser is called. It can be used to reset state or preprocess the source code or tokens. The +passes `ErrorHandler` should be used to report lexing errors. + +The `getTokens()` method returns the current token array, in the usual `token_get_all()` format. This method is not +used by the parser (which uses `getNextToken()`), but is useful in combination with the token position attributes. + +The `handleHaltCompiler()` method is called whenever a `T_HALT_COMPILER` token is encountered. It has to return the +remaining string after the construct (not including `();`). + +The `getNextToken()` method returns the ID of the next token (as defined by the `Parser::T_*` constants). If no more +tokens are available it must return `0`, which is the ID of the `EOF` token. Furthermore the string content of the +token should be written into the by-reference `$value` parameter (which will then be available as `$n` in the parser). + +### Attribute handling + +The other two by-ref variables `$startAttributes` and `$endAttributes` define which attributes will eventually be +assigned to the generated nodes: The parser will take the `$startAttributes` from the first token which is part of the +node and the `$endAttributes` from the last token that is part of the node. + +E.g. if the tokens `T_FUNCTION T_STRING ... '{' ... '}'` constitute a node, then the `$startAttributes` from the +`T_FUNCTION` token will be taken and the `$endAttributes` from the `'}'` token. + +An application of custom attributes is storing the exact original formatting of literals: While the parser does retain +some information about the formatting of integers (like decimal vs. hexadecimal) or strings (like used quote type), it +does not preserve the exact original formatting (e.g. leading zeros for integers or escape sequences in strings). This +can be remedied by storing the original value in an attribute: + +```php +use PhpParser\Lexer; +use PhpParser\Parser\Tokens; + +class KeepOriginalValueLexer extends Lexer // or Lexer\Emulative +{ + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { + $tokenId = parent::getNextToken($value, $startAttributes, $endAttributes); + + if ($tokenId == Tokens::T_CONSTANT_ENCAPSED_STRING // non-interpolated string + || $tokenId == Tokens::T_ENCAPSED_AND_WHITESPACE // interpolated string + || $tokenId == Tokens::T_LNUMBER // integer + || $tokenId == Tokens::T_DNUMBER // floating point number + ) { + // could also use $startAttributes, doesn't really matter here + $endAttributes['originalValue'] = $value; + } + + return $tokenId; + } +} +``` diff --git a/www/multitube/vendor/nikic/php-parser/grammar/README.md b/www/multitube/vendor/nikic/php-parser/grammar/README.md new file mode 100644 index 0000000..3f1698a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/README.md @@ -0,0 +1,28 @@ +What do all those files mean? +============================= + + * `php5.y`: PHP 5 grammar written in a pseudo language + * `php7.y`: PHP 7 grammar written in a pseudo language + * `tokens.y`: Tokens definition shared between PHP 5 and PHP 7 grammars + * `parser.template`: A `kmyacc` parser prototype file for PHP + * `tokens.template`: A `kmyacc` prototype file for the `Tokens` class + * `rebuildParsers.php`: Preprocesses the grammar and builds the parser using `kmyacc` + +.phpy pseudo language +===================== + +The `.y` file is a normal grammer in `kmyacc` (`yacc`) style, with some transformations +applied to it: + + * Nodes are created using the syntax `Name[..., ...]`. This is transformed into + `new Name(..., ..., attributes())` + * Some function-like constructs are resolved (see `rebuildParsers.php` for a list) + +Building the parser +=================== + +In order to rebuild the parser, you need [moriyoshi's fork of kmyacc](https://github.com/moriyoshi/kmyacc-forked). +After you compiled/installed it, run the `rebuildParsers.php` script. + +By default only the `Parser.php` is built. If you want to additionally emit debug symbols and create `y.output`, run the +script with `--debug`. If you want to retain the preprocessed grammar pass `--keep-tmp-grammar`. diff --git a/www/multitube/vendor/nikic/php-parser/grammar/parser.template b/www/multitube/vendor/nikic/php-parser/grammar/parser.template new file mode 100644 index 0000000..fff893f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/parser.template @@ -0,0 +1,103 @@ +semValue +#semval($,%t) $this->semValue +#semval(%n) $this->stackPos-(%l-%n) +#semval(%n,%t) $this->stackPos-(%l-%n) + +namespace PhpParser\Parser; + +use PhpParser\Error; +use PhpParser\Node; +use PhpParser\Node\Expr; +use PhpParser\Node\Name; +use PhpParser\Node\Scalar; +use PhpParser\Node\Stmt; +#include; + +/* This is an automatically GENERATED file, which should not be manually edited. + * Instead edit one of the following: + * * the grammar files grammar/php5.y or grammar/php7.y + * * the skeleton file grammar/parser.template + * * the preprocessing script grammar/rebuildParsers.php + */ +class #(-p) extends \PhpParser\ParserAbstract +{ + protected $tokenToSymbolMapSize = #(YYMAXLEX); + protected $actionTableSize = #(YYLAST); + protected $gotoTableSize = #(YYGLAST); + + protected $invalidSymbol = #(YYBADCH); + protected $errorSymbol = #(YYINTERRTOK); + protected $defaultAction = #(YYDEFAULT); + protected $unexpectedTokenRule = #(YYUNEXPECTED); + + protected $YY2TBLSTATE = #(YY2TBLSTATE); + protected $YYNLSTATES = #(YYNLSTATES); + + protected $symbolToName = array( + #listvar terminals + ); + + protected $tokenToSymbol = array( + #listvar yytranslate + ); + + protected $action = array( + #listvar yyaction + ); + + protected $actionCheck = array( + #listvar yycheck + ); + + protected $actionBase = array( + #listvar yybase + ); + + protected $actionDefault = array( + #listvar yydefault + ); + + protected $goto = array( + #listvar yygoto + ); + + protected $gotoCheck = array( + #listvar yygcheck + ); + + protected $gotoBase = array( + #listvar yygbase + ); + + protected $gotoDefault = array( + #listvar yygdefault + ); + + protected $ruleToNonTerminal = array( + #listvar yylhs + ); + + protected $ruleToLength = array( + #listvar yylen + ); +#if -t + + protected $productions = array( + #production-strings; + ); +#endif +#reduce + + protected function reduceRule%n() { + %b + } +#noact + + protected function reduceRule%n() { + $this->semValue = $this->semStack[$this->stackPos]; + } +#endreduce +} +#tailcode; diff --git a/www/multitube/vendor/nikic/php-parser/grammar/php5.y b/www/multitube/vendor/nikic/php-parser/grammar/php5.y new file mode 100644 index 0000000..7938438 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/php5.y @@ -0,0 +1,1009 @@ +%pure_parser +%expect 6 + +%tokens + +%% + +start: + top_statement_list { $$ = $this->handleNamespaces($1); } +; + +top_statement_list_ex: + top_statement_list_ex top_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +top_statement_list: + top_statement_list_ex + { makeNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +reserved_non_modifiers: + T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND + | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE + | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH + | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO + | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT + | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS + | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER +; + +semi_reserved: + reserved_non_modifiers + | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC +; + +identifier: + T_STRING { $$ = $1; } + | semi_reserved { $$ = $1; } +; + +namespace_name_parts: + T_STRING { init($1); } + | namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); } +; + +namespace_name: + namespace_name_parts { $$ = Name[$1]; } +; + +top_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } + | T_NAMESPACE namespace_name ';' + { $$ = Stmt\Namespace_[$2, null]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($$); } + | T_NAMESPACE namespace_name '{' top_statement_list '}' + { $$ = Stmt\Namespace_[$2, $4]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_NAMESPACE '{' top_statement_list '}' + { $$ = Stmt\Namespace_[null, $3]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_USE use_declarations ';' { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } + | T_USE use_type use_declarations ';' { $$ = Stmt\Use_[$3, $2]; } + | group_use_declaration ';' { $$ = $1; } + | T_CONST constant_declaration_list ';' { $$ = Stmt\Const_[$2]; } +; + +use_type: + T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } + | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } +; + +/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */ +group_use_declaration: + T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, $2]; } + | T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($4, stackAttributes(#4)), $7, $2]; } + | T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($2, stackAttributes(#2)), $5, Stmt\Use_::TYPE_UNKNOWN]; } + | T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, Stmt\Use_::TYPE_UNKNOWN]; } +; + +unprefixed_use_declarations: + unprefixed_use_declarations ',' unprefixed_use_declaration + { push($1, $3); } + | unprefixed_use_declaration { init($1); } +; + +use_declarations: + use_declarations ',' use_declaration { push($1, $3); } + | use_declaration { init($1); } +; + +inline_use_declarations: + inline_use_declarations ',' inline_use_declaration { push($1, $3); } + | inline_use_declaration { init($1); } +; + +unprefixed_use_declaration: + namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | namespace_name T_AS T_STRING + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +use_declaration: + unprefixed_use_declaration { $$ = $1; } + | T_NS_SEPARATOR unprefixed_use_declaration { $$ = $2; } +; + +inline_use_declaration: + unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } + | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } +; + +constant_declaration_list: + constant_declaration_list ',' constant_declaration { push($1, $3); } + | constant_declaration { init($1); } +; + +constant_declaration: + T_STRING '=' static_scalar { $$ = Node\Const_[$1, $3]; } +; + +class_const_list: + class_const_list ',' class_const { push($1, $3); } + | class_const { init($1); } +; + +class_const: + identifier '=' static_scalar { $$ = Node\Const_[$1, $3]; } +; + +inner_statement_list_ex: + inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +inner_statement_list: + inner_statement_list_ex + { makeNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +inner_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } +; + +non_empty_statement: + '{' inner_statement_list '}' + { + if ($2) { + $$ = $2; prependLeadingComments($$); + } else { + makeNop($$, $this->startAttributeStack[#1]); + if (null === $$) { $$ = array(); } + } + } + | T_IF parentheses_expr statement elseif_list else_single + { $$ = Stmt\If_[$2, ['stmts' => toArray($3), 'elseifs' => $4, 'else' => $5]]; } + | T_IF parentheses_expr ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' + { $$ = Stmt\If_[$2, ['stmts' => $4, 'elseifs' => $5, 'else' => $6]]; } + | T_WHILE parentheses_expr while_statement { $$ = Stmt\While_[$2, $3]; } + | T_DO statement T_WHILE parentheses_expr ';' { $$ = Stmt\Do_ [$4, toArray($2)]; } + | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement + { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } + | T_SWITCH parentheses_expr switch_case_list { $$ = Stmt\Switch_[$2, $3]; } + | T_BREAK ';' { $$ = Stmt\Break_[null]; } + | T_BREAK expr ';' { $$ = Stmt\Break_[$2]; } + | T_CONTINUE ';' { $$ = Stmt\Continue_[null]; } + | T_CONTINUE expr ';' { $$ = Stmt\Continue_[$2]; } + | T_RETURN ';' { $$ = Stmt\Return_[null]; } + | T_RETURN expr ';' { $$ = Stmt\Return_[$2]; } + | yield_expr ';' { $$ = $1; } + | T_GLOBAL global_var_list ';' { $$ = Stmt\Global_[$2]; } + | T_STATIC static_var_list ';' { $$ = Stmt\Static_[$2]; } + | T_ECHO expr_list ';' { $$ = Stmt\Echo_[$2]; } + | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } + | expr ';' { $$ = $1; } + | T_UNSET '(' variables_list ')' ';' { $$ = Stmt\Unset_[$3]; } + | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } + | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } + | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } + | T_TRY '{' inner_statement_list '}' catches optional_finally + { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } + | T_THROW expr ';' { $$ = Stmt\Throw_[$2]; } + | T_GOTO T_STRING ';' { $$ = Stmt\Goto_[$2]; } + | T_STRING ':' { $$ = Stmt\Label[$1]; } + | expr error { $$ = $1; } + | error { $$ = array(); /* means: no statement */ } +; + +statement: + non_empty_statement { $$ = $1; } + | ';' + { makeNop($$, $this->startAttributeStack[#1]); + if ($$ === null) $$ = array(); /* means: no statement */ } +; + +catches: + /* empty */ { init(); } + | catches catch { push($1, $2); } +; + +catch: + T_CATCH '(' name T_VARIABLE ')' '{' inner_statement_list '}' + { $$ = Stmt\Catch_[array($3), parseVar($4), $7]; } +; + +optional_finally: + /* empty */ { $$ = null; } + | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } +; + +variables_list: + variable { init($1); } + | variables_list ',' variable { push($1, $3); } +; + +optional_ref: + /* empty */ { $$ = false; } + | '&' { $$ = true; } +; + +optional_ellipsis: + /* empty */ { $$ = false; } + | T_ELLIPSIS { $$ = true; } +; + +function_declaration_statement: + T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' + { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } +; + +class_declaration_statement: + class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}' + { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; + $this->checkClass($$, #2); } + | T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}' + { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; + $this->checkInterface($$, #2); } + | T_TRAIT T_STRING '{' class_statement_list '}' + { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } +; + +class_entry_type: + T_CLASS { $$ = 0; } + | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +extends_from: + /* empty */ { $$ = null; } + | T_EXTENDS class_name { $$ = $2; } +; + +interface_extends_list: + /* empty */ { $$ = array(); } + | T_EXTENDS class_name_list { $$ = $2; } +; + +implements_list: + /* empty */ { $$ = array(); } + | T_IMPLEMENTS class_name_list { $$ = $2; } +; + +class_name_list: + class_name { init($1); } + | class_name_list ',' class_name { push($1, $3); } +; + +for_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } +; + +foreach_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } +; + +declare_statement: + non_empty_statement { $$ = toArray($1); } + | ';' { $$ = null; } + | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } +; + +declare_list: + declare_list_element { init($1); } + | declare_list ',' declare_list_element { push($1, $3); } +; + +declare_list_element: + T_STRING '=' static_scalar { $$ = Stmt\DeclareDeclare[$1, $3]; } +; + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list T_ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } +; + +case_list: + /* empty */ { init(); } + | case_list case { push($1, $2); } +; + +case: + T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } + | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } +; + +case_separator: + ':' + | ';' +; + +while_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } +; + +elseif_list: + /* empty */ { init(); } + | elseif_list elseif { push($1, $2); } +; + +elseif: + T_ELSEIF parentheses_expr statement { $$ = Stmt\ElseIf_[$2, toArray($3)]; } +; + +new_elseif_list: + /* empty */ { init(); } + | new_elseif_list new_elseif { push($1, $2); } +; + +new_elseif: + T_ELSEIF parentheses_expr ':' inner_statement_list { $$ = Stmt\ElseIf_[$2, $4]; } +; + +else_single: + /* empty */ { $$ = null; } + | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } +; + +new_else_single: + /* empty */ { $$ = null; } + | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } +; + +foreach_variable: + variable { $$ = array($1, false); } + | '&' variable { $$ = array($2, true); } + | list_expr { $$ = array($1, false); } +; + +parameter_list: + non_empty_parameter_list { $$ = $1; } + | /* empty */ { $$ = array(); } +; + +non_empty_parameter_list: + parameter { init($1); } + | non_empty_parameter_list ',' parameter { push($1, $3); } +; + +parameter: + optional_param_type optional_ref optional_ellipsis T_VARIABLE + { $$ = Node\Param[parseVar($4), null, $1, $2, $3]; $this->checkParam($$); } + | optional_param_type optional_ref optional_ellipsis T_VARIABLE '=' static_scalar + { $$ = Node\Param[parseVar($4), $6, $1, $2, $3]; $this->checkParam($$); } +; + +type: + name { $$ = $1; } + | T_ARRAY { $$ = 'array'; } + | T_CALLABLE { $$ = 'callable'; } +; + +optional_param_type: + /* empty */ { $$ = null; } + | type { $$ = $1; } +; + +optional_return_type: + /* empty */ { $$ = null; } + | ':' type { $$ = $2; } +; + +argument_list: + '(' ')' { $$ = array(); } + | '(' non_empty_argument_list ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = array(Node\Arg[$2, false, false]); } +; + +non_empty_argument_list: + argument { init($1); } + | non_empty_argument_list ',' argument { push($1, $3); } +; + +argument: + expr { $$ = Node\Arg[$1, false, false]; } + | '&' variable { $$ = Node\Arg[$2, true, false]; } + | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } +; + +global_var_list: + global_var_list ',' global_var { push($1, $3); } + | global_var { init($1); } +; + +global_var: + T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } + | '$' variable { $$ = Expr\Variable[$2]; } + | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } +; + +static_var_list: + static_var_list ',' static_var { push($1, $3); } + | static_var { init($1); } +; + +static_var: + T_VARIABLE { $$ = Stmt\StaticVar[parseVar($1), null]; } + | T_VARIABLE '=' static_scalar { $$ = Stmt\StaticVar[parseVar($1), $3]; } +; + +class_statement_list: + class_statement_list class_statement { push($1, $2); } + | /* empty */ { init(); } +; + +class_statement: + variable_modifiers property_declaration_list ';' + { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } + | T_CONST class_const_list ';' { $$ = Stmt\ClassConst[$2, 0]; } + | method_modifiers T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type method_body + { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; + $this->checkClassMethod($$, #1); } + | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } +; + +trait_adaptations: + ';' { $$ = array(); } + | '{' trait_adaptation_list '}' { $$ = $2; } +; + +trait_adaptation_list: + /* empty */ { init(); } + | trait_adaptation_list trait_adaptation { push($1, $2); } +; + +trait_adaptation: + trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' + { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } + | trait_method_reference T_AS member_modifier identifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } + | trait_method_reference T_AS member_modifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } + | trait_method_reference T_AS T_STRING ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } + | trait_method_reference T_AS reserved_non_modifiers ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } +; + +trait_method_reference_fully_qualified: + name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = array($1, $3); } +; +trait_method_reference: + trait_method_reference_fully_qualified { $$ = $1; } + | identifier { $$ = array(null, $1); } +; + +method_body: + ';' /* abstract method */ { $$ = null; } + | '{' inner_statement_list '}' { $$ = $2; } +; + +variable_modifiers: + non_empty_member_modifiers { $$ = $1; } + | T_VAR { $$ = 0; } +; + +method_modifiers: + /* empty */ { $$ = 0; } + | non_empty_member_modifiers { $$ = $1; } +; + +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } +; + +member_modifier: + T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } + | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } + | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } + | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +property_declaration_list: + property_declaration { init($1); } + | property_declaration_list ',' property_declaration { push($1, $3); } +; + +property_declaration: + T_VARIABLE { $$ = Stmt\PropertyProperty[parseVar($1), null]; } + | T_VARIABLE '=' static_scalar { $$ = Stmt\PropertyProperty[parseVar($1), $3]; } +; + +expr_list: + expr_list ',' expr { push($1, $3); } + | expr { init($1); } +; + +for_expr: + /* empty */ { $$ = array(); } + | expr_list { $$ = $1; } +; + +expr: + variable { $$ = $1; } + | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; } + | variable '=' '&' new_expr { $$ = Expr\AssignRef[$1, $4]; } + | new_expr { $$ = $1; } + | T_CLONE expr { $$ = Expr\Clone_[$2]; } + | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } + | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } + | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } + | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } + | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } + | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } + | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } + | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } + | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } + | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } + | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } + | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } + | variable T_INC { $$ = Expr\PostInc[$1]; } + | T_INC variable { $$ = Expr\PreInc [$2]; } + | variable T_DEC { $$ = Expr\PostDec[$1]; } + | T_DEC variable { $$ = Expr\PreDec [$2]; } + | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } + | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' expr { $$ = Expr\BooleanNot[$2]; } + | '~' expr { $$ = Expr\BitwiseNot[$2]; } + | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } + | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } + | parentheses_expr { $$ = $1; } + /* we need a separate '(' new_expr ')' rule to avoid problems caused by a s/r conflict */ + | '(' new_expr ')' { $$ = $2; } + | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } + | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } + | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } + | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } + | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } + | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } + | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } + | T_EVAL parentheses_expr { $$ = Expr\Eval_[$2]; } + | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } + | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } + | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } + | T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; } + | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } + | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } + | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } + | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } + | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } + | T_EXIT exit_expr + { $attrs = attributes(); + $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $$ = new Expr\Exit_($2, $attrs); } + | '@' expr { $$ = Expr\ErrorSuppress[$2]; } + | scalar { $$ = $1; } + | array_expr { $$ = $1; } + | scalar_dereference { $$ = $1; } + | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } + | T_PRINT expr { $$ = Expr\Print_[$2]; } + | T_YIELD { $$ = Expr\Yield_[null, null]; } + | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } + | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } + | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } +; + +parentheses_expr: + '(' expr ')' { $$ = $2; } + | '(' yield_expr ')' { $$ = $2; } +; + +yield_expr: + T_YIELD expr { $$ = Expr\Yield_[$2, null]; } + | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } +; + +array_expr: + T_ARRAY '(' array_pair_list ')' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; + $$ = new Expr\Array_($3, $attrs); } + | '[' array_pair_list ']' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; + $$ = new Expr\Array_($2, $attrs); } +; + +scalar_dereference: + array_expr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' + { $attrs = attributes(); $attrs['kind'] = strKind($1); + $$ = Expr\ArrayDimFetch[new Scalar\String_(Scalar\String_::parse($1), $attrs), $3]; } + | constant '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | scalar_dereference '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +anonymous_class: + T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' + { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); + $this->checkClass($$[0], -1); } + +new_expr: + T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } + | T_NEW anonymous_class + { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } +; + +lexical_vars: + /* empty */ { $$ = array(); } + | T_USE '(' lexical_var_list ')' { $$ = $3; } +; + +lexical_var_list: + lexical_var { init($1); } + | lexical_var_list ',' lexical_var { push($1, $3); } +; + +lexical_var: + optional_ref T_VARIABLE { $$ = Expr\ClosureUse[parseVar($2), $1]; } +; + +function_call: + name argument_list { $$ = Expr\FuncCall[$1, $2]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier argument_list + { $$ = Expr\StaticCall[$1, $3, $4]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '{' expr '}' argument_list + { $$ = Expr\StaticCall[$1, $4, $6]; } + | static_property argument_list { + if ($1 instanceof Node\Expr\StaticPropertyFetch) { + $$ = Expr\StaticCall[$1->class, Expr\Variable[$1->name], $2]; + } elseif ($1 instanceof Node\Expr\ArrayDimFetch) { + $tmp = $1; + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + } + + $$ = Expr\StaticCall[$tmp->var->class, $1, $2]; + $tmp->var = Expr\Variable[$tmp->var->name]; + } else { + throw new \Exception; + } + } + | variable_without_objects argument_list + { $$ = Expr\FuncCall[$1, $2]; } + | function_call '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +class_name: + T_STATIC { $$ = Name[$1]; } + | name { $$ = $1; } +; + +name: + namespace_name_parts { $$ = Name[$1]; } + | T_NS_SEPARATOR namespace_name_parts { $$ = Name\FullyQualified[$2]; } + | T_NAMESPACE T_NS_SEPARATOR namespace_name_parts { $$ = Name\Relative[$3]; } +; + +class_name_reference: + class_name { $$ = $1; } + | dynamic_class_name_reference { $$ = $1; } +; + +dynamic_class_name_reference: + object_access_for_dcnr { $$ = $1; } + | base_variable { $$ = $1; } +; + +class_name_or_var: + class_name { $$ = $1; } + | reference_variable { $$ = $1; } +; + +object_access_for_dcnr: + base_variable T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | object_access_for_dcnr T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | object_access_for_dcnr '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | object_access_for_dcnr '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +exit_expr: + /* empty */ { $$ = null; } + | '(' ')' { $$ = null; } + | parentheses_expr { $$ = $1; } +; + +backticks_expr: + /* empty */ { $$ = array(); } + | T_ENCAPSED_AND_WHITESPACE + { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`', false)]); } + | encaps_list { parseEncapsed($1, '`', false); $$ = $1; } +; + +ctor_arguments: + /* empty */ { $$ = array(); } + | argument_list { $$ = $1; } +; + +common_scalar: + T_LNUMBER { $$ = $this->parseLNumber($1, attributes(), true); } + | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } + | T_CONSTANT_ENCAPSED_STRING + { $attrs = attributes(); $attrs['kind'] = strKind($1); + $$ = new Scalar\String_(Scalar\String_::parse($1, false), $attrs); } + | T_LINE { $$ = Scalar\MagicConst\Line[]; } + | T_FILE { $$ = Scalar\MagicConst\File[]; } + | T_DIR { $$ = Scalar\MagicConst\Dir[]; } + | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } + | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } + | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } + | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } + | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + $$ = new Scalar\String_(Scalar\String_::parseDocString($1, $2, false), $attrs); } + | T_START_HEREDOC T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + $$ = new Scalar\String_('', $attrs); } +; + +static_scalar: + common_scalar { $$ = $1; } + | class_name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = Expr\ClassConstFetch[$1, $3]; } + | name { $$ = Expr\ConstFetch[$1]; } + | T_ARRAY '(' static_array_pair_list ')' { $$ = Expr\Array_[$3]; } + | '[' static_array_pair_list ']' { $$ = Expr\Array_[$2]; } + | static_operation { $$ = $1; } +; + +static_operation: + static_scalar T_BOOLEAN_OR static_scalar { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | static_scalar T_BOOLEAN_AND static_scalar { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | static_scalar T_LOGICAL_OR static_scalar { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | static_scalar T_LOGICAL_AND static_scalar { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | static_scalar T_LOGICAL_XOR static_scalar { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | static_scalar '|' static_scalar { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | static_scalar '&' static_scalar { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | static_scalar '^' static_scalar { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | static_scalar '.' static_scalar { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | static_scalar '+' static_scalar { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | static_scalar '-' static_scalar { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | static_scalar '*' static_scalar { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | static_scalar '/' static_scalar { $$ = Expr\BinaryOp\Div [$1, $3]; } + | static_scalar '%' static_scalar { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | static_scalar T_SL static_scalar { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | static_scalar T_SR static_scalar { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | static_scalar T_POW static_scalar { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' static_scalar %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' static_scalar %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' static_scalar { $$ = Expr\BooleanNot[$2]; } + | '~' static_scalar { $$ = Expr\BitwiseNot[$2]; } + | static_scalar T_IS_IDENTICAL static_scalar { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | static_scalar T_IS_NOT_IDENTICAL static_scalar { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | static_scalar T_IS_EQUAL static_scalar { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | static_scalar T_IS_NOT_EQUAL static_scalar { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | static_scalar '<' static_scalar { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | static_scalar T_IS_SMALLER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | static_scalar '>' static_scalar { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | static_scalar T_IS_GREATER_OR_EQUAL static_scalar { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | static_scalar '?' static_scalar ':' static_scalar { $$ = Expr\Ternary[$1, $3, $5]; } + | static_scalar '?' ':' static_scalar { $$ = Expr\Ternary[$1, null, $4]; } + | static_scalar '[' static_scalar ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | '(' static_scalar ')' { $$ = $2; } +; + +constant: + name { $$ = Expr\ConstFetch[$1]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier + { $$ = Expr\ClassConstFetch[$1, $3]; } +; + +scalar: + common_scalar { $$ = $1; } + | constant { $$ = $1; } + | '"' encaps_list '"' + { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } + | T_START_HEREDOC encaps_list T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + parseEncapsedDoc($2, true); $$ = new Scalar\Encapsed($2, $attrs); } +; + +static_array_pair_list: + /* empty */ { $$ = array(); } + | non_empty_static_array_pair_list optional_comma { $$ = $1; } +; + +optional_comma: + /* empty */ + | ',' +; + +non_empty_static_array_pair_list: + non_empty_static_array_pair_list ',' static_array_pair { push($1, $3); } + | static_array_pair { init($1); } +; + +static_array_pair: + static_scalar T_DOUBLE_ARROW static_scalar { $$ = Expr\ArrayItem[$3, $1, false]; } + | static_scalar { $$ = Expr\ArrayItem[$1, null, false]; } +; + +variable: + object_access { $$ = $1; } + | base_variable { $$ = $1; } + | function_call { $$ = $1; } + | new_expr_array_deref { $$ = $1; } +; + +new_expr_array_deref: + '(' new_expr ')' '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$2, $5]; } + | new_expr_array_deref '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + /* alternative array syntax missing intentionally */ +; + +object_access: + variable_or_new_expr T_OBJECT_OPERATOR object_property + { $$ = Expr\PropertyFetch[$1, $3]; } + | variable_or_new_expr T_OBJECT_OPERATOR object_property argument_list + { $$ = Expr\MethodCall[$1, $3, $4]; } + | object_access argument_list { $$ = Expr\FuncCall[$1, $2]; } + | object_access '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | object_access '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +variable_or_new_expr: + variable { $$ = $1; } + | '(' new_expr ')' { $$ = $2; } +; + +variable_without_objects: + reference_variable { $$ = $1; } + | '$' variable_without_objects { $$ = Expr\Variable[$2]; } +; + +base_variable: + variable_without_objects { $$ = $1; } + | static_property { $$ = $1; } +; + +static_property: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' reference_variable + { $$ = Expr\StaticPropertyFetch[$1, $4]; } + | static_property_with_arrays { $$ = $1; } +; + +static_property_with_arrays: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM T_VARIABLE + { $$ = Expr\StaticPropertyFetch[$1, parseVar($3)]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM '$' '{' expr '}' + { $$ = Expr\StaticPropertyFetch[$1, $5]; } + | static_property_with_arrays '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | static_property_with_arrays '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } +; + +reference_variable: + reference_variable '[' dim_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | reference_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } + | '$' '{' expr '}' { $$ = Expr\Variable[$3]; } +; + +dim_offset: + /* empty */ { $$ = null; } + | expr { $$ = $1; } +; + +object_property: + T_STRING { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | variable_without_objects { $$ = $1; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +list_expr: + T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } +; + +list_expr_elements: + list_expr_elements ',' list_expr_element { push($1, $3); } + | list_expr_element { init($1); } +; + +list_expr_element: + variable { $$ = Expr\ArrayItem[$1, null, false]; } + | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } + | /* empty */ { $$ = null; } +; + +array_pair_list: + /* empty */ { $$ = array(); } + | non_empty_array_pair_list optional_comma { $$ = $1; } +; + +non_empty_array_pair_list: + non_empty_array_pair_list ',' array_pair { push($1, $3); } + | array_pair { init($1); } +; + +array_pair: + expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | expr { $$ = Expr\ArrayItem[$1, null, false]; } + | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } + | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } +; + +encaps_list: + encaps_list encaps_var { push($1, $2); } + | encaps_list encaps_string_part { push($1, $2); } + | encaps_var { init($1); } + | encaps_string_part encaps_var { init($1, $2); } +; + +encaps_string_part: + T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } +; + +encaps_base_var: + T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +encaps_var: + encaps_base_var { $$ = $1; } + | encaps_base_var '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | encaps_base_var T_OBJECT_OPERATOR T_STRING { $$ = Expr\PropertyFetch[$1, $3]; } + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' + { $$ = Expr\ArrayDimFetch[Expr\Variable[$2], $4]; } + | T_CURLY_OPEN variable '}' { $$ = $2; } +; + +encaps_var_offset: + T_STRING { $$ = Scalar\String_[$1]; } + | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } + | T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +%% diff --git a/www/multitube/vendor/nikic/php-parser/grammar/php7.y b/www/multitube/vendor/nikic/php-parser/grammar/php7.y new file mode 100644 index 0000000..f9b599b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/php7.y @@ -0,0 +1,965 @@ +%pure_parser +%expect 2 + +%tokens + +%% + +start: + top_statement_list { $$ = $this->handleNamespaces($1); } +; + +top_statement_list_ex: + top_statement_list_ex top_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +top_statement_list: + top_statement_list_ex + { makeNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +reserved_non_modifiers: + T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND + | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE + | T_ENDWHILE | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH + | T_FINALLY | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO + | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT + | T_BREAK | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS + | T_CLASS_C | T_TRAIT_C | T_FUNC_C | T_METHOD_C | T_LINE | T_FILE | T_DIR | T_NS_C | T_HALT_COMPILER +; + +semi_reserved: + reserved_non_modifiers + | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC +; + +identifier: + T_STRING { $$ = $1; } + | semi_reserved { $$ = $1; } +; + +namespace_name_parts: + T_STRING { init($1); } + | namespace_name_parts T_NS_SEPARATOR T_STRING { push($1, $3); } +; + +namespace_name: + namespace_name_parts { $$ = Name[$1]; } +; + +semi: + ';' { /* nothing */ } + | error { /* nothing */ } +; + +no_comma: + /* empty */ { /* nothing */ } + | ',' { $this->emitError(new Error('A trailing comma is not allowed here', attributes())); } +; + +optional_comma: + /* empty */ + | ',' + +top_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { $$ = Stmt\HaltCompiler[$this->lexer->handleHaltCompiler()]; } + | T_NAMESPACE namespace_name semi + { $$ = Stmt\Namespace_[$2, null]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($$); } + | T_NAMESPACE namespace_name '{' top_statement_list '}' + { $$ = Stmt\Namespace_[$2, $4]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_NAMESPACE '{' top_statement_list '}' + { $$ = Stmt\Namespace_[null, $3]; + $$->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($$); } + | T_USE use_declarations semi { $$ = Stmt\Use_[$2, Stmt\Use_::TYPE_NORMAL]; } + | T_USE use_type use_declarations semi { $$ = Stmt\Use_[$3, $2]; } + | group_use_declaration semi { $$ = $1; } + | T_CONST constant_declaration_list semi { $$ = Stmt\Const_[$2]; } +; + +use_type: + T_FUNCTION { $$ = Stmt\Use_::TYPE_FUNCTION; } + | T_CONST { $$ = Stmt\Use_::TYPE_CONSTANT; } +; + +/* Using namespace_name_parts here to avoid s/r conflict on T_NS_SEPARATOR */ +group_use_declaration: + T_USE use_type namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, $2]; } + | T_USE use_type T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' unprefixed_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($4, stackAttributes(#4)), $7, $2]; } + | T_USE namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($2, stackAttributes(#2)), $5, Stmt\Use_::TYPE_UNKNOWN]; } + | T_USE T_NS_SEPARATOR namespace_name_parts T_NS_SEPARATOR '{' inline_use_declarations '}' + { $$ = Stmt\GroupUse[new Name($3, stackAttributes(#3)), $6, Stmt\Use_::TYPE_UNKNOWN]; } +; + +unprefixed_use_declarations: + non_empty_unprefixed_use_declarations optional_comma { $$ = $1; } +; + +non_empty_unprefixed_use_declarations: + non_empty_unprefixed_use_declarations ',' unprefixed_use_declaration + { push($1, $3); } + | unprefixed_use_declaration { init($1); } +; + +use_declarations: + non_empty_use_declarations no_comma { $$ = $1; } +; + +non_empty_use_declarations: + non_empty_use_declarations ',' use_declaration { push($1, $3); } + | use_declaration { init($1); } +; + +inline_use_declarations: + non_empty_inline_use_declarations optional_comma { $$ = $1; } +; + +non_empty_inline_use_declarations: + non_empty_inline_use_declarations ',' inline_use_declaration + { push($1, $3); } + | inline_use_declaration { init($1); } +; + +unprefixed_use_declaration: + namespace_name + { $$ = Stmt\UseUse[$1, null, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #1); } + | namespace_name T_AS T_STRING + { $$ = Stmt\UseUse[$1, $3, Stmt\Use_::TYPE_UNKNOWN]; $this->checkUseUse($$, #3); } +; + +use_declaration: + unprefixed_use_declaration { $$ = $1; } + | T_NS_SEPARATOR unprefixed_use_declaration { $$ = $2; } +; + +inline_use_declaration: + unprefixed_use_declaration { $$ = $1; $$->type = Stmt\Use_::TYPE_NORMAL; } + | use_type unprefixed_use_declaration { $$ = $2; $$->type = $1; } +; + +constant_declaration_list: + non_empty_constant_declaration_list no_comma { $$ = $1; } +; + +non_empty_constant_declaration_list: + non_empty_constant_declaration_list ',' constant_declaration + { push($1, $3); } + | constant_declaration { init($1); } +; + +constant_declaration: + T_STRING '=' expr { $$ = Node\Const_[$1, $3]; } +; + +class_const_list: + non_empty_class_const_list no_comma { $$ = $1; } +; + +non_empty_class_const_list: + non_empty_class_const_list ',' class_const { push($1, $3); } + | class_const { init($1); } +; + +class_const: + identifier '=' expr { $$ = Node\Const_[$1, $3]; } +; + +inner_statement_list_ex: + inner_statement_list_ex inner_statement { pushNormalizing($1, $2); } + | /* empty */ { init(); } +; + +inner_statement_list: + inner_statement_list_ex + { makeNop($nop, $this->lookaheadStartAttributes); + if ($nop !== null) { $1[] = $nop; } $$ = $1; } +; + +inner_statement: + statement { $$ = $1; } + | function_declaration_statement { $$ = $1; } + | class_declaration_statement { $$ = $1; } + | T_HALT_COMPILER + { throw new Error('__HALT_COMPILER() can only be used from the outermost scope', attributes()); } +; + +non_empty_statement: + '{' inner_statement_list '}' + { + if ($2) { + $$ = $2; prependLeadingComments($$); + } else { + makeNop($$, $this->startAttributeStack[#1]); + if (null === $$) { $$ = array(); } + } + } + | T_IF '(' expr ')' statement elseif_list else_single + { $$ = Stmt\If_[$3, ['stmts' => toArray($5), 'elseifs' => $6, 'else' => $7]]; } + | T_IF '(' expr ')' ':' inner_statement_list new_elseif_list new_else_single T_ENDIF ';' + { $$ = Stmt\If_[$3, ['stmts' => $6, 'elseifs' => $7, 'else' => $8]]; } + | T_WHILE '(' expr ')' while_statement { $$ = Stmt\While_[$3, $5]; } + | T_DO statement T_WHILE '(' expr ')' ';' { $$ = Stmt\Do_ [$5, toArray($2)]; } + | T_FOR '(' for_expr ';' for_expr ';' for_expr ')' for_statement + { $$ = Stmt\For_[['init' => $3, 'cond' => $5, 'loop' => $7, 'stmts' => $9]]; } + | T_SWITCH '(' expr ')' switch_case_list { $$ = Stmt\Switch_[$3, $5]; } + | T_BREAK optional_expr semi { $$ = Stmt\Break_[$2]; } + | T_CONTINUE optional_expr semi { $$ = Stmt\Continue_[$2]; } + | T_RETURN optional_expr semi { $$ = Stmt\Return_[$2]; } + | T_GLOBAL global_var_list semi { $$ = Stmt\Global_[$2]; } + | T_STATIC static_var_list semi { $$ = Stmt\Static_[$2]; } + | T_ECHO expr_list semi { $$ = Stmt\Echo_[$2]; } + | T_INLINE_HTML { $$ = Stmt\InlineHTML[$1]; } + | expr semi { $$ = $1; } + | T_UNSET '(' variables_list ')' semi { $$ = Stmt\Unset_[$3]; } + | T_FOREACH '(' expr T_AS foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $5[0], ['keyVar' => null, 'byRef' => $5[1], 'stmts' => $7]]; } + | T_FOREACH '(' expr T_AS variable T_DOUBLE_ARROW foreach_variable ')' foreach_statement + { $$ = Stmt\Foreach_[$3, $7[0], ['keyVar' => $5, 'byRef' => $7[1], 'stmts' => $9]]; } + | T_DECLARE '(' declare_list ')' declare_statement { $$ = Stmt\Declare_[$3, $5]; } + | T_TRY '{' inner_statement_list '}' catches optional_finally + { $$ = Stmt\TryCatch[$3, $5, $6]; $this->checkTryCatch($$); } + | T_THROW expr semi { $$ = Stmt\Throw_[$2]; } + | T_GOTO T_STRING semi { $$ = Stmt\Goto_[$2]; } + | T_STRING ':' { $$ = Stmt\Label[$1]; } + | error { $$ = array(); /* means: no statement */ } +; + +statement: + non_empty_statement { $$ = $1; } + | ';' + { makeNop($$, $this->startAttributeStack[#1]); + if ($$ === null) $$ = array(); /* means: no statement */ } +; + +catches: + /* empty */ { init(); } + | catches catch { push($1, $2); } +; + +name_union: + name { init($1); } + | name_union '|' name { push($1, $3); } +; + +catch: + T_CATCH '(' name_union T_VARIABLE ')' '{' inner_statement_list '}' + { $$ = Stmt\Catch_[$3, parseVar($4), $7]; } +; + +optional_finally: + /* empty */ { $$ = null; } + | T_FINALLY '{' inner_statement_list '}' { $$ = Stmt\Finally_[$3]; } +; + +variables_list: + non_empty_variables_list no_comma { $$ = $1; } +; + +non_empty_variables_list: + variable { init($1); } + | non_empty_variables_list ',' variable { push($1, $3); } +; + +optional_ref: + /* empty */ { $$ = false; } + | '&' { $$ = true; } +; + +optional_ellipsis: + /* empty */ { $$ = false; } + | T_ELLIPSIS { $$ = true; } +; + +function_declaration_statement: + T_FUNCTION optional_ref T_STRING '(' parameter_list ')' optional_return_type '{' inner_statement_list '}' + { $$ = Stmt\Function_[$3, ['byRef' => $2, 'params' => $5, 'returnType' => $7, 'stmts' => $9]]; } +; + +class_declaration_statement: + class_entry_type T_STRING extends_from implements_list '{' class_statement_list '}' + { $$ = Stmt\Class_[$2, ['type' => $1, 'extends' => $3, 'implements' => $4, 'stmts' => $6]]; + $this->checkClass($$, #2); } + | T_INTERFACE T_STRING interface_extends_list '{' class_statement_list '}' + { $$ = Stmt\Interface_[$2, ['extends' => $3, 'stmts' => $5]]; + $this->checkInterface($$, #2); } + | T_TRAIT T_STRING '{' class_statement_list '}' + { $$ = Stmt\Trait_[$2, ['stmts' => $4]]; } +; + +class_entry_type: + T_CLASS { $$ = 0; } + | T_ABSTRACT T_CLASS { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL T_CLASS { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +extends_from: + /* empty */ { $$ = null; } + | T_EXTENDS class_name { $$ = $2; } +; + +interface_extends_list: + /* empty */ { $$ = array(); } + | T_EXTENDS class_name_list { $$ = $2; } +; + +implements_list: + /* empty */ { $$ = array(); } + | T_IMPLEMENTS class_name_list { $$ = $2; } +; + +class_name_list: + non_empty_class_name_list no_comma { $$ = $1; } +; + +non_empty_class_name_list: + class_name { init($1); } + | non_empty_class_name_list ',' class_name { push($1, $3); } +; + +for_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOR ';' { $$ = $2; } +; + +foreach_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDFOREACH ';' { $$ = $2; } +; + +declare_statement: + non_empty_statement { $$ = toArray($1); } + | ';' { $$ = null; } + | ':' inner_statement_list T_ENDDECLARE ';' { $$ = $2; } +; + +declare_list: + non_empty_declare_list no_comma { $$ = $1; } +; + +non_empty_declare_list: + declare_list_element { init($1); } + | non_empty_declare_list ',' declare_list_element { push($1, $3); } +; + +declare_list_element: + T_STRING '=' expr { $$ = Stmt\DeclareDeclare[$1, $3]; } +; + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list T_ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list T_ENDSWITCH ';' { $$ = $3; } +; + +case_list: + /* empty */ { init(); } + | case_list case { push($1, $2); } +; + +case: + T_CASE expr case_separator inner_statement_list_ex { $$ = Stmt\Case_[$2, $4]; } + | T_DEFAULT case_separator inner_statement_list_ex { $$ = Stmt\Case_[null, $3]; } +; + +case_separator: + ':' + | ';' +; + +while_statement: + statement { $$ = toArray($1); } + | ':' inner_statement_list T_ENDWHILE ';' { $$ = $2; } +; + +elseif_list: + /* empty */ { init(); } + | elseif_list elseif { push($1, $2); } +; + +elseif: + T_ELSEIF '(' expr ')' statement { $$ = Stmt\ElseIf_[$3, toArray($5)]; } +; + +new_elseif_list: + /* empty */ { init(); } + | new_elseif_list new_elseif { push($1, $2); } +; + +new_elseif: + T_ELSEIF '(' expr ')' ':' inner_statement_list { $$ = Stmt\ElseIf_[$3, $6]; } +; + +else_single: + /* empty */ { $$ = null; } + | T_ELSE statement { $$ = Stmt\Else_[toArray($2)]; } +; + +new_else_single: + /* empty */ { $$ = null; } + | T_ELSE ':' inner_statement_list { $$ = Stmt\Else_[$3]; } +; + +foreach_variable: + variable { $$ = array($1, false); } + | '&' variable { $$ = array($2, true); } + | list_expr { $$ = array($1, false); } + | array_short_syntax { $$ = array($1, false); } +; + +parameter_list: + non_empty_parameter_list no_comma { $$ = $1; } + | /* empty */ { $$ = array(); } +; + +non_empty_parameter_list: + parameter { init($1); } + | non_empty_parameter_list ',' parameter { push($1, $3); } +; + +parameter: + optional_param_type optional_ref optional_ellipsis T_VARIABLE + { $$ = Node\Param[parseVar($4), null, $1, $2, $3]; $this->checkParam($$); } + | optional_param_type optional_ref optional_ellipsis T_VARIABLE '=' expr + { $$ = Node\Param[parseVar($4), $6, $1, $2, $3]; $this->checkParam($$); } +; + +type_expr: + type { $$ = $1; } + | '?' type { $$ = Node\NullableType[$2]; } +; + +type: + name { $$ = $this->handleBuiltinTypes($1); } + | T_ARRAY { $$ = 'array'; } + | T_CALLABLE { $$ = 'callable'; } +; + +optional_param_type: + /* empty */ { $$ = null; } + | type_expr { $$ = $1; } +; + +optional_return_type: + /* empty */ { $$ = null; } + | ':' type_expr { $$ = $2; } +; + +argument_list: + '(' ')' { $$ = array(); } + | '(' non_empty_argument_list no_comma ')' { $$ = $2; } +; + +non_empty_argument_list: + argument { init($1); } + | non_empty_argument_list ',' argument { push($1, $3); } +; + +argument: + expr { $$ = Node\Arg[$1, false, false]; } + | '&' variable { $$ = Node\Arg[$2, true, false]; } + | T_ELLIPSIS expr { $$ = Node\Arg[$2, false, true]; } +; + +global_var_list: + non_empty_global_var_list no_comma { $$ = $1; } +; + +non_empty_global_var_list: + non_empty_global_var_list ',' global_var { push($1, $3); } + | global_var { init($1); } +; + +global_var: + simple_variable { $$ = Expr\Variable[$1]; } +; + +static_var_list: + non_empty_static_var_list no_comma { $$ = $1; } +; + +non_empty_static_var_list: + non_empty_static_var_list ',' static_var { push($1, $3); } + | static_var { init($1); } +; + +static_var: + T_VARIABLE { $$ = Stmt\StaticVar[parseVar($1), null]; } + | T_VARIABLE '=' expr { $$ = Stmt\StaticVar[parseVar($1), $3]; } +; + +class_statement_list: + class_statement_list class_statement { push($1, $2); } + | /* empty */ { init(); } +; + +class_statement: + variable_modifiers property_declaration_list ';' + { $$ = Stmt\Property[$1, $2]; $this->checkProperty($$, #1); } + | method_modifiers T_CONST class_const_list ';' + { $$ = Stmt\ClassConst[$3, $1]; $this->checkClassConst($$, #1); } + | method_modifiers T_FUNCTION optional_ref identifier '(' parameter_list ')' optional_return_type method_body + { $$ = Stmt\ClassMethod[$4, ['type' => $1, 'byRef' => $3, 'params' => $6, 'returnType' => $8, 'stmts' => $9]]; + $this->checkClassMethod($$, #1); } + | T_USE class_name_list trait_adaptations { $$ = Stmt\TraitUse[$2, $3]; } +; + +trait_adaptations: + ';' { $$ = array(); } + | '{' trait_adaptation_list '}' { $$ = $2; } +; + +trait_adaptation_list: + /* empty */ { init(); } + | trait_adaptation_list trait_adaptation { push($1, $2); } +; + +trait_adaptation: + trait_method_reference_fully_qualified T_INSTEADOF class_name_list ';' + { $$ = Stmt\TraitUseAdaptation\Precedence[$1[0], $1[1], $3]; } + | trait_method_reference T_AS member_modifier identifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, $4]; } + | trait_method_reference T_AS member_modifier ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], $3, null]; } + | trait_method_reference T_AS T_STRING ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } + | trait_method_reference T_AS reserved_non_modifiers ';' + { $$ = Stmt\TraitUseAdaptation\Alias[$1[0], $1[1], null, $3]; } +; + +trait_method_reference_fully_qualified: + name T_PAAMAYIM_NEKUDOTAYIM identifier { $$ = array($1, $3); } +; +trait_method_reference: + trait_method_reference_fully_qualified { $$ = $1; } + | identifier { $$ = array(null, $1); } +; + +method_body: + ';' /* abstract method */ { $$ = null; } + | '{' inner_statement_list '}' { $$ = $2; } +; + +variable_modifiers: + non_empty_member_modifiers { $$ = $1; } + | T_VAR { $$ = 0; } +; + +method_modifiers: + /* empty */ { $$ = 0; } + | non_empty_member_modifiers { $$ = $1; } +; + +non_empty_member_modifiers: + member_modifier { $$ = $1; } + | non_empty_member_modifiers member_modifier { $this->checkModifier($1, $2, #2); $$ = $1 | $2; } +; + +member_modifier: + T_PUBLIC { $$ = Stmt\Class_::MODIFIER_PUBLIC; } + | T_PROTECTED { $$ = Stmt\Class_::MODIFIER_PROTECTED; } + | T_PRIVATE { $$ = Stmt\Class_::MODIFIER_PRIVATE; } + | T_STATIC { $$ = Stmt\Class_::MODIFIER_STATIC; } + | T_ABSTRACT { $$ = Stmt\Class_::MODIFIER_ABSTRACT; } + | T_FINAL { $$ = Stmt\Class_::MODIFIER_FINAL; } +; + +property_declaration_list: + non_empty_property_declaration_list no_comma { $$ = $1; } +; + +non_empty_property_declaration_list: + property_declaration { init($1); } + | non_empty_property_declaration_list ',' property_declaration + { push($1, $3); } +; + +property_declaration: + T_VARIABLE { $$ = Stmt\PropertyProperty[parseVar($1), null]; } + | T_VARIABLE '=' expr { $$ = Stmt\PropertyProperty[parseVar($1), $3]; } +; + +expr_list: + non_empty_expr_list no_comma { $$ = $1; } +; + +non_empty_expr_list: + non_empty_expr_list ',' expr { push($1, $3); } + | expr { init($1); } +; + +for_expr: + /* empty */ { $$ = array(); } + | expr_list { $$ = $1; } +; + +expr: + variable { $$ = $1; } + | list_expr '=' expr { $$ = Expr\Assign[$1, $3]; } + | array_short_syntax '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' expr { $$ = Expr\Assign[$1, $3]; } + | variable '=' '&' variable { $$ = Expr\AssignRef[$1, $4]; } + | new_expr { $$ = $1; } + | T_CLONE expr { $$ = Expr\Clone_[$2]; } + | variable T_PLUS_EQUAL expr { $$ = Expr\AssignOp\Plus [$1, $3]; } + | variable T_MINUS_EQUAL expr { $$ = Expr\AssignOp\Minus [$1, $3]; } + | variable T_MUL_EQUAL expr { $$ = Expr\AssignOp\Mul [$1, $3]; } + | variable T_DIV_EQUAL expr { $$ = Expr\AssignOp\Div [$1, $3]; } + | variable T_CONCAT_EQUAL expr { $$ = Expr\AssignOp\Concat [$1, $3]; } + | variable T_MOD_EQUAL expr { $$ = Expr\AssignOp\Mod [$1, $3]; } + | variable T_AND_EQUAL expr { $$ = Expr\AssignOp\BitwiseAnd[$1, $3]; } + | variable T_OR_EQUAL expr { $$ = Expr\AssignOp\BitwiseOr [$1, $3]; } + | variable T_XOR_EQUAL expr { $$ = Expr\AssignOp\BitwiseXor[$1, $3]; } + | variable T_SL_EQUAL expr { $$ = Expr\AssignOp\ShiftLeft [$1, $3]; } + | variable T_SR_EQUAL expr { $$ = Expr\AssignOp\ShiftRight[$1, $3]; } + | variable T_POW_EQUAL expr { $$ = Expr\AssignOp\Pow [$1, $3]; } + | variable T_INC { $$ = Expr\PostInc[$1]; } + | T_INC variable { $$ = Expr\PreInc [$2]; } + | variable T_DEC { $$ = Expr\PostDec[$1]; } + | T_DEC variable { $$ = Expr\PreDec [$2]; } + | expr T_BOOLEAN_OR expr { $$ = Expr\BinaryOp\BooleanOr [$1, $3]; } + | expr T_BOOLEAN_AND expr { $$ = Expr\BinaryOp\BooleanAnd[$1, $3]; } + | expr T_LOGICAL_OR expr { $$ = Expr\BinaryOp\LogicalOr [$1, $3]; } + | expr T_LOGICAL_AND expr { $$ = Expr\BinaryOp\LogicalAnd[$1, $3]; } + | expr T_LOGICAL_XOR expr { $$ = Expr\BinaryOp\LogicalXor[$1, $3]; } + | expr '|' expr { $$ = Expr\BinaryOp\BitwiseOr [$1, $3]; } + | expr '&' expr { $$ = Expr\BinaryOp\BitwiseAnd[$1, $3]; } + | expr '^' expr { $$ = Expr\BinaryOp\BitwiseXor[$1, $3]; } + | expr '.' expr { $$ = Expr\BinaryOp\Concat [$1, $3]; } + | expr '+' expr { $$ = Expr\BinaryOp\Plus [$1, $3]; } + | expr '-' expr { $$ = Expr\BinaryOp\Minus [$1, $3]; } + | expr '*' expr { $$ = Expr\BinaryOp\Mul [$1, $3]; } + | expr '/' expr { $$ = Expr\BinaryOp\Div [$1, $3]; } + | expr '%' expr { $$ = Expr\BinaryOp\Mod [$1, $3]; } + | expr T_SL expr { $$ = Expr\BinaryOp\ShiftLeft [$1, $3]; } + | expr T_SR expr { $$ = Expr\BinaryOp\ShiftRight[$1, $3]; } + | expr T_POW expr { $$ = Expr\BinaryOp\Pow [$1, $3]; } + | '+' expr %prec T_INC { $$ = Expr\UnaryPlus [$2]; } + | '-' expr %prec T_INC { $$ = Expr\UnaryMinus[$2]; } + | '!' expr { $$ = Expr\BooleanNot[$2]; } + | '~' expr { $$ = Expr\BitwiseNot[$2]; } + | expr T_IS_IDENTICAL expr { $$ = Expr\BinaryOp\Identical [$1, $3]; } + | expr T_IS_NOT_IDENTICAL expr { $$ = Expr\BinaryOp\NotIdentical [$1, $3]; } + | expr T_IS_EQUAL expr { $$ = Expr\BinaryOp\Equal [$1, $3]; } + | expr T_IS_NOT_EQUAL expr { $$ = Expr\BinaryOp\NotEqual [$1, $3]; } + | expr T_SPACESHIP expr { $$ = Expr\BinaryOp\Spaceship [$1, $3]; } + | expr '<' expr { $$ = Expr\BinaryOp\Smaller [$1, $3]; } + | expr T_IS_SMALLER_OR_EQUAL expr { $$ = Expr\BinaryOp\SmallerOrEqual[$1, $3]; } + | expr '>' expr { $$ = Expr\BinaryOp\Greater [$1, $3]; } + | expr T_IS_GREATER_OR_EQUAL expr { $$ = Expr\BinaryOp\GreaterOrEqual[$1, $3]; } + | expr T_INSTANCEOF class_name_reference { $$ = Expr\Instanceof_[$1, $3]; } + | '(' expr ')' { $$ = $2; } + | expr '?' expr ':' expr { $$ = Expr\Ternary[$1, $3, $5]; } + | expr '?' ':' expr { $$ = Expr\Ternary[$1, null, $4]; } + | expr T_COALESCE expr { $$ = Expr\BinaryOp\Coalesce[$1, $3]; } + | T_ISSET '(' variables_list ')' { $$ = Expr\Isset_[$3]; } + | T_EMPTY '(' expr ')' { $$ = Expr\Empty_[$3]; } + | T_INCLUDE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE]; } + | T_INCLUDE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_INCLUDE_ONCE]; } + | T_EVAL '(' expr ')' { $$ = Expr\Eval_[$3]; } + | T_REQUIRE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE]; } + | T_REQUIRE_ONCE expr { $$ = Expr\Include_[$2, Expr\Include_::TYPE_REQUIRE_ONCE]; } + | T_INT_CAST expr { $$ = Expr\Cast\Int_ [$2]; } + | T_DOUBLE_CAST expr { $$ = Expr\Cast\Double [$2]; } + | T_STRING_CAST expr { $$ = Expr\Cast\String_ [$2]; } + | T_ARRAY_CAST expr { $$ = Expr\Cast\Array_ [$2]; } + | T_OBJECT_CAST expr { $$ = Expr\Cast\Object_ [$2]; } + | T_BOOL_CAST expr { $$ = Expr\Cast\Bool_ [$2]; } + | T_UNSET_CAST expr { $$ = Expr\Cast\Unset_ [$2]; } + | T_EXIT exit_expr + { $attrs = attributes(); + $attrs['kind'] = strtolower($1) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $$ = new Expr\Exit_($2, $attrs); } + | '@' expr { $$ = Expr\ErrorSuppress[$2]; } + | scalar { $$ = $1; } + | '`' backticks_expr '`' { $$ = Expr\ShellExec[$2]; } + | T_PRINT expr { $$ = Expr\Print_[$2]; } + | T_YIELD { $$ = Expr\Yield_[null, null]; } + | T_YIELD expr { $$ = Expr\Yield_[$2, null]; } + | T_YIELD expr T_DOUBLE_ARROW expr { $$ = Expr\Yield_[$4, $2]; } + | T_YIELD_FROM expr { $$ = Expr\YieldFrom[$2]; } + | T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => false, 'byRef' => $2, 'params' => $4, 'uses' => $6, 'returnType' => $7, 'stmts' => $9]]; } + | T_STATIC T_FUNCTION optional_ref '(' parameter_list ')' lexical_vars optional_return_type + '{' inner_statement_list '}' + { $$ = Expr\Closure[['static' => true, 'byRef' => $3, 'params' => $5, 'uses' => $7, 'returnType' => $8, 'stmts' => $10]]; } +; + +anonymous_class: + T_CLASS ctor_arguments extends_from implements_list '{' class_statement_list '}' + { $$ = array(Stmt\Class_[null, ['type' => 0, 'extends' => $3, 'implements' => $4, 'stmts' => $6]], $2); + $this->checkClass($$[0], -1); } + +new_expr: + T_NEW class_name_reference ctor_arguments { $$ = Expr\New_[$2, $3]; } + | T_NEW anonymous_class + { list($class, $ctorArgs) = $2; $$ = Expr\New_[$class, $ctorArgs]; } +; + +lexical_vars: + /* empty */ { $$ = array(); } + | T_USE '(' lexical_var_list ')' { $$ = $3; } +; + +lexical_var_list: + non_empty_lexical_var_list no_comma { $$ = $1; } +; + +non_empty_lexical_var_list: + lexical_var { init($1); } + | non_empty_lexical_var_list ',' lexical_var { push($1, $3); } +; + +lexical_var: + optional_ref T_VARIABLE { $$ = Expr\ClosureUse[parseVar($2), $1]; } +; + +function_call: + name argument_list { $$ = Expr\FuncCall[$1, $2]; } + | callable_expr argument_list { $$ = Expr\FuncCall[$1, $2]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM member_name argument_list + { $$ = Expr\StaticCall[$1, $3, $4]; } +; + +class_name: + T_STATIC { $$ = Name[$1]; } + | name { $$ = $1; } +; + +name: + namespace_name_parts { $$ = Name[$1]; } + | T_NS_SEPARATOR namespace_name_parts { $$ = Name\FullyQualified[$2]; } + | T_NAMESPACE T_NS_SEPARATOR namespace_name_parts { $$ = Name\Relative[$3]; } +; + +class_name_reference: + class_name { $$ = $1; } + | new_variable { $$ = $1; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +class_name_or_var: + class_name { $$ = $1; } + | dereferencable { $$ = $1; } +; + +exit_expr: + /* empty */ { $$ = null; } + | '(' optional_expr ')' { $$ = $2; } +; + +backticks_expr: + /* empty */ { $$ = array(); } + | T_ENCAPSED_AND_WHITESPACE + { $$ = array(Scalar\EncapsedStringPart[Scalar\String_::parseEscapeSequences($1, '`')]); } + | encaps_list { parseEncapsed($1, '`', true); $$ = $1; } +; + +ctor_arguments: + /* empty */ { $$ = array(); } + | argument_list { $$ = $1; } +; + +constant: + name { $$ = Expr\ConstFetch[$1]; } + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM identifier + { $$ = Expr\ClassConstFetch[$1, $3]; } + /* We interpret and isolated FOO:: as an unfinished class constant fetch. It could also be + an unfinished static property fetch or unfinished scoped call. */ + | class_name_or_var T_PAAMAYIM_NEKUDOTAYIM error + { $$ = Expr\ClassConstFetch[$1, new Expr\Error(stackAttributes(#3))]; $this->errorState = 2; } +; + +array_short_syntax: + '[' array_pair_list ']' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_SHORT; + $$ = new Expr\Array_($2, $attrs); } +; + +dereferencable_scalar: + T_ARRAY '(' array_pair_list ')' + { $attrs = attributes(); $attrs['kind'] = Expr\Array_::KIND_LONG; + $$ = new Expr\Array_($3, $attrs); } + | array_short_syntax { $$ = $1; } + | T_CONSTANT_ENCAPSED_STRING + { $attrs = attributes(); $attrs['kind'] = strKind($1); + $$ = new Scalar\String_(Scalar\String_::parse($1), $attrs); } +; + +scalar: + T_LNUMBER { $$ = $this->parseLNumber($1, attributes()); } + | T_DNUMBER { $$ = Scalar\DNumber[Scalar\DNumber::parse($1)]; } + | T_LINE { $$ = Scalar\MagicConst\Line[]; } + | T_FILE { $$ = Scalar\MagicConst\File[]; } + | T_DIR { $$ = Scalar\MagicConst\Dir[]; } + | T_CLASS_C { $$ = Scalar\MagicConst\Class_[]; } + | T_TRAIT_C { $$ = Scalar\MagicConst\Trait_[]; } + | T_METHOD_C { $$ = Scalar\MagicConst\Method[]; } + | T_FUNC_C { $$ = Scalar\MagicConst\Function_[]; } + | T_NS_C { $$ = Scalar\MagicConst\Namespace_[]; } + | dereferencable_scalar { $$ = $1; } + | constant { $$ = $1; } + | T_START_HEREDOC T_ENCAPSED_AND_WHITESPACE T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + $$ = new Scalar\String_(Scalar\String_::parseDocString($1, $2), $attrs); } + | T_START_HEREDOC T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + $$ = new Scalar\String_('', $attrs); } + | '"' encaps_list '"' + { $attrs = attributes(); $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + parseEncapsed($2, '"', true); $$ = new Scalar\Encapsed($2, $attrs); } + | T_START_HEREDOC encaps_list T_END_HEREDOC + { $attrs = attributes(); setDocStringAttrs($attrs, $1); + parseEncapsedDoc($2, true); $$ = new Scalar\Encapsed($2, $attrs); } +; + +optional_expr: + /* empty */ { $$ = null; } + | expr { $$ = $1; } +; + +dereferencable: + variable { $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } +; + +callable_expr: + callable_variable { $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } +; + +callable_variable: + simple_variable { $$ = Expr\Variable[$1]; } + | dereferencable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | constant '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | dereferencable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | function_call { $$ = $1; } + | dereferencable T_OBJECT_OPERATOR property_name argument_list + { $$ = Expr\MethodCall[$1, $3, $4]; } +; + +variable: + callable_variable { $$ = $1; } + | static_member { $$ = $1; } + | dereferencable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } +; + +simple_variable: + T_VARIABLE { $$ = parseVar($1); } + | '$' '{' expr '}' { $$ = $3; } + | '$' simple_variable { $$ = Expr\Variable[$2]; } + | '$' error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +static_member: + class_name_or_var T_PAAMAYIM_NEKUDOTAYIM simple_variable + { $$ = Expr\StaticPropertyFetch[$1, $3]; } +; + +new_variable: + simple_variable { $$ = Expr\Variable[$1]; } + | new_variable '[' optional_expr ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | new_variable '{' expr '}' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | new_variable T_OBJECT_OPERATOR property_name { $$ = Expr\PropertyFetch[$1, $3]; } + | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { $$ = Expr\StaticPropertyFetch[$1, $3]; } + | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable { $$ = Expr\StaticPropertyFetch[$1, $3]; } +; + +member_name: + identifier { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | simple_variable { $$ = Expr\Variable[$1]; } +; + +property_name: + T_STRING { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | simple_variable { $$ = Expr\Variable[$1]; } + | error { $$ = Expr\Error[]; $this->errorState = 2; } +; + +list_expr: + T_LIST '(' list_expr_elements ')' { $$ = Expr\List_[$3]; } +; + +list_expr_elements: + list_expr_elements ',' list_expr_element { push($1, $3); } + | list_expr_element { init($1); } +; + +list_expr_element: + variable { $$ = Expr\ArrayItem[$1, null, false]; } + | list_expr { $$ = Expr\ArrayItem[$1, null, false]; } + | expr T_DOUBLE_ARROW variable { $$ = Expr\ArrayItem[$3, $1, false]; } + | expr T_DOUBLE_ARROW list_expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | /* empty */ { $$ = null; } +; + +array_pair_list: + inner_array_pair_list + { $$ = $1; $end = count($$)-1; if ($$[$end] === null) unset($$[$end]); } +; + +inner_array_pair_list: + inner_array_pair_list ',' array_pair { push($1, $3); } + | array_pair { init($1); } +; + +array_pair: + expr T_DOUBLE_ARROW expr { $$ = Expr\ArrayItem[$3, $1, false]; } + | expr { $$ = Expr\ArrayItem[$1, null, false]; } + | expr T_DOUBLE_ARROW '&' variable { $$ = Expr\ArrayItem[$4, $1, true]; } + | '&' variable { $$ = Expr\ArrayItem[$2, null, true]; } + | /* empty */ { $$ = null; } +; + +encaps_list: + encaps_list encaps_var { push($1, $2); } + | encaps_list encaps_string_part { push($1, $2); } + | encaps_var { init($1); } + | encaps_string_part encaps_var { init($1, $2); } +; + +encaps_string_part: + T_ENCAPSED_AND_WHITESPACE { $$ = Scalar\EncapsedStringPart[$1]; } +; + +encaps_base_var: + T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +encaps_var: + encaps_base_var { $$ = $1; } + | encaps_base_var '[' encaps_var_offset ']' { $$ = Expr\ArrayDimFetch[$1, $3]; } + | encaps_base_var T_OBJECT_OPERATOR T_STRING { $$ = Expr\PropertyFetch[$1, $3]; } + | T_DOLLAR_OPEN_CURLY_BRACES expr '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '}' { $$ = Expr\Variable[$2]; } + | T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME '[' expr ']' '}' + { $$ = Expr\ArrayDimFetch[Expr\Variable[$2], $4]; } + | T_CURLY_OPEN variable '}' { $$ = $2; } +; + +encaps_var_offset: + T_STRING { $$ = Scalar\String_[$1]; } + | T_NUM_STRING { $$ = $this->parseNumString($1, attributes()); } + | '-' T_NUM_STRING { $$ = $this->parseNumString('-' . $2, attributes()); } + | T_VARIABLE { $$ = Expr\Variable[parseVar($1)]; } +; + +%% diff --git a/www/multitube/vendor/nikic/php-parser/grammar/rebuildParsers.php b/www/multitube/vendor/nikic/php-parser/grammar/rebuildParsers.php new file mode 100644 index 0000000..340b0ea --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/rebuildParsers.php @@ -0,0 +1,263 @@ + 'Php5', + __DIR__ . '/php7.y' => 'Php7', +]; + +$tokensFile = __DIR__ . '/tokens.y'; +$tokensTemplate = __DIR__ . '/tokens.template'; +$skeletonFile = __DIR__ . '/parser.template'; +$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy'; +$tmpResultFile = __DIR__ . '/tmp_parser.php'; +$resultDir = __DIR__ . '/../lib/PhpParser/Parser'; +$tokensResultsFile = $resultDir . '/Tokens.php'; + +// check for kmyacc.exe binary in this directory, otherwise fall back to global name +$kmyacc = __DIR__ . '/kmyacc.exe'; +if (!file_exists($kmyacc)) { + $kmyacc = 'kmyacc'; +} + +$options = array_flip($argv); +$optionDebug = isset($options['--debug']); +$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']); + +/////////////////////////////// +/// Utility regex constants /// +/////////////////////////////// + +const LIB = '(?(DEFINE) + (?\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\') + (?"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+") + (?(?&singleQuotedString)|(?&doubleQuotedString)) + (?/\*[^*]*+(?:\*(?!/)[^*]*+)*+\*/) + (?\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+}) +)'; + +const PARAMS = '\[(?[^[\]]*+(?:\[(?¶ms)\][^[\]]*+)*+)\]'; +const ARGS = '\((?[^()]*+(?:\((?&args)\)[^()]*+)*+)\)'; + +/////////////////// +/// Main script /// +/////////////////// + +$tokens = file_get_contents($tokensFile); + +foreach ($grammarFileToName as $grammarFile => $name) { + echo "Building temporary $name grammar file.\n"; + + $grammarCode = file_get_contents($grammarFile); + $grammarCode = str_replace('%tokens', $tokens, $grammarCode); + + $grammarCode = resolveNodes($grammarCode); + $grammarCode = resolveMacros($grammarCode); + $grammarCode = resolveStackAccess($grammarCode); + + file_put_contents($tmpGrammarFile, $grammarCode); + + $additionalArgs = $optionDebug ? '-t -v' : ''; + + echo "Building $name parser.\n"; + $output = trim(shell_exec("$kmyacc $additionalArgs -l -m $skeletonFile -p $name $tmpGrammarFile 2>&1")); + echo "Output: \"$output\"\n"; + + $resultCode = file_get_contents($tmpResultFile); + $resultCode = removeTrailingWhitespace($resultCode); + + ensureDirExists($resultDir); + file_put_contents("$resultDir/$name.php", $resultCode); + unlink($tmpResultFile); + + echo "Building token definition.\n"; + $output = trim(shell_exec("$kmyacc -l -m $tokensTemplate $tmpGrammarFile 2>&1")); + assert($output === ''); + rename($tmpResultFile, $tokensResultsFile); + + if (!$optionKeepTmpGrammar) { + unlink($tmpGrammarFile); + } +} + +/////////////////////////////// +/// Preprocessing functions /// +/////////////////////////////// + +function resolveNodes($code) { + return preg_replace_callback( + '~\b(?[A-Z][a-zA-Z_\\\\]++)\s*' . PARAMS . '~', + function($matches) { + // recurse + $matches['params'] = resolveNodes($matches['params']); + + $params = magicSplit( + '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', + $matches['params'] + ); + + $paramCode = ''; + foreach ($params as $param) { + $paramCode .= $param . ', '; + } + + return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())'; + }, + $code + ); +} + +function resolveMacros($code) { + return preg_replace_callback( + '~\b(?)(?!array\()(?[a-z][A-Za-z]++)' . ARGS . '~', + function($matches) { + // recurse + $matches['args'] = resolveMacros($matches['args']); + + $name = $matches['name']; + $args = magicSplit( + '(?:' . PARAMS . '|' . ARGS . ')(*SKIP)(*FAIL)|,', + $matches['args'] + ); + + if ('attributes' == $name) { + assertArgs(0, $args, $name); + return '$this->startAttributeStack[#1] + $this->endAttributes'; + } + + if ('stackAttributes' == $name) { + assertArgs(1, $args, $name); + return '$this->startAttributeStack[' . $args[0] . ']' + . ' + $this->endAttributeStack[' . $args[0] . ']'; + } + + if ('init' == $name) { + return '$$ = array(' . implode(', ', $args) . ')'; + } + + if ('push' == $name) { + assertArgs(2, $args, $name); + + return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0]; + } + + if ('pushNormalizing' == $name) { + assertArgs(2, $args, $name); + + return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); }' + . ' else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }'; + } + + if ('toArray' == $name) { + assertArgs(1, $args, $name); + + return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')'; + } + + if ('parseVar' == $name) { + assertArgs(1, $args, $name); + + return 'substr(' . $args[0] . ', 1)'; + } + + if ('parseEncapsed' == $name) { + assertArgs(3, $args, $name); + + return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {' + . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }'; + } + + if ('parseEncapsedDoc' == $name) { + assertArgs(2, $args, $name); + + return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) {' + . ' $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, ' . $args[1] . '); } }' + . ' $s->value = preg_replace(\'~(\r\n|\n|\r)\z~\', \'\', $s->value);' + . ' if (\'\' === $s->value) array_pop(' . $args[0] . ');'; + } + + if ('makeNop' == $name) { + assertArgs(2, $args, $name); + + return '$startAttributes = ' . $args[1] . ';' + . ' if (isset($startAttributes[\'comments\']))' + . ' { ' . $args[0] . ' = new Stmt\Nop([\'comments\' => $startAttributes[\'comments\']]); }' + . ' else { ' . $args[0] . ' = null; }'; + } + + if ('strKind' == $name) { + assertArgs(1, $args, $name); + + return '(' . $args[0] . '[0] === "\'" || (' . $args[0] . '[1] === "\'" && ' + . '(' . $args[0] . '[0] === \'b\' || ' . $args[0] . '[0] === \'B\')) ' + . '? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED)'; + } + + if ('setDocStringAttrs' == $name) { + assertArgs(2, $args, $name); + + return $args[0] . '[\'kind\'] = strpos(' . $args[1] . ', "\'") === false ' + . '? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; ' + . 'preg_match(\'/\A[bB]?<<<[ \t]*[\\\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\\\'"]?(?:\r\n|\n|\r)\z/\', ' . $args[1] . ', $matches); ' + . $args[0] . '[\'docLabel\'] = $matches[1];'; + } + + if ('prependLeadingComments' == $name) { + assertArgs(1, $args, $name); + + return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; ' + . 'if (!empty($attrs[\'comments\'])) {' + . '$stmts[0]->setAttribute(\'comments\', ' + . 'array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }'; + } + + return $matches[0]; + }, + $code + ); +} + +function assertArgs($num, $args, $name) { + if ($num != count($args)) { + die('Wrong argument count for ' . $name . '().'); + } +} + +function resolveStackAccess($code) { + $code = preg_replace('/\$\d+/', '$this->semStack[$0]', $code); + $code = preg_replace('/#(\d+)/', '$$1', $code); + return $code; +} + +function removeTrailingWhitespace($code) { + $lines = explode("\n", $code); + $lines = array_map('rtrim', $lines); + return implode("\n", $lines); +} + +function ensureDirExists($dir) { + if (!is_dir($dir)) { + mkdir($dir, 0777, true); + } +} + +////////////////////////////// +/// Regex helper functions /// +////////////////////////////// + +function regex($regex) { + return '~' . LIB . '(?:' . str_replace('~', '\~', $regex) . ')~'; +} + +function magicSplit($regex, $string) { + $pieces = preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string); + + foreach ($pieces as &$piece) { + $piece = trim($piece); + } + + if ($pieces === ['']) { + return []; + } + + return $pieces; +} diff --git a/www/multitube/vendor/nikic/php-parser/grammar/tokens.template b/www/multitube/vendor/nikic/php-parser/grammar/tokens.template new file mode 100644 index 0000000..ba4e490 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/tokens.template @@ -0,0 +1,17 @@ +semValue +#semval($,%t) $this->semValue +#semval(%n) $this->stackPos-(%l-%n) +#semval(%n,%t) $this->stackPos-(%l-%n) + +namespace PhpParser\Parser; +#include; + +/* GENERATED file based on grammar/tokens.y */ +final class Tokens +{ +#tokenval + const %s = %n; +#endtokenval +} diff --git a/www/multitube/vendor/nikic/php-parser/grammar/tokens.y b/www/multitube/vendor/nikic/php-parser/grammar/tokens.y new file mode 100644 index 0000000..2b54f80 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/grammar/tokens.y @@ -0,0 +1,113 @@ +/* We currently rely on the token ID mapping to be the same between PHP 5 and PHP 7 - so the same lexer can be used for + * both. This is enforced by sharing this token file. */ + +%left T_INCLUDE T_INCLUDE_ONCE T_EVAL T_REQUIRE T_REQUIRE_ONCE +%left ',' +%left T_LOGICAL_OR +%left T_LOGICAL_XOR +%left T_LOGICAL_AND +%right T_PRINT +%right T_YIELD +%right T_DOUBLE_ARROW +%right T_YIELD_FROM +%left '=' T_PLUS_EQUAL T_MINUS_EQUAL T_MUL_EQUAL T_DIV_EQUAL T_CONCAT_EQUAL T_MOD_EQUAL T_AND_EQUAL T_OR_EQUAL T_XOR_EQUAL T_SL_EQUAL T_SR_EQUAL T_POW_EQUAL +%left '?' ':' +%right T_COALESCE +%left T_BOOLEAN_OR +%left T_BOOLEAN_AND +%left '|' +%left '^' +%left '&' +%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL T_IS_IDENTICAL T_IS_NOT_IDENTICAL T_SPACESHIP +%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL +%left T_SL T_SR +%left '+' '-' '.' +%left '*' '/' '%' +%right '!' +%nonassoc T_INSTANCEOF +%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' +%right T_POW +%right '[' +%nonassoc T_NEW T_CLONE +%token T_EXIT +%token T_IF +%left T_ELSEIF +%left T_ELSE +%left T_ENDIF +%token T_LNUMBER +%token T_DNUMBER +%token T_STRING +%token T_STRING_VARNAME +%token T_VARIABLE +%token T_NUM_STRING +%token T_INLINE_HTML +%token T_CHARACTER +%token T_BAD_CHARACTER +%token T_ENCAPSED_AND_WHITESPACE +%token T_CONSTANT_ENCAPSED_STRING +%token T_ECHO +%token T_DO +%token T_WHILE +%token T_ENDWHILE +%token T_FOR +%token T_ENDFOR +%token T_FOREACH +%token T_ENDFOREACH +%token T_DECLARE +%token T_ENDDECLARE +%token T_AS +%token T_SWITCH +%token T_ENDSWITCH +%token T_CASE +%token T_DEFAULT +%token T_BREAK +%token T_CONTINUE +%token T_GOTO +%token T_FUNCTION +%token T_CONST +%token T_RETURN +%token T_TRY +%token T_CATCH +%token T_FINALLY +%token T_THROW +%token T_USE +%token T_INSTEADOF +%token T_GLOBAL +%right T_STATIC T_ABSTRACT T_FINAL T_PRIVATE T_PROTECTED T_PUBLIC +%token T_VAR +%token T_UNSET +%token T_ISSET +%token T_EMPTY +%token T_HALT_COMPILER +%token T_CLASS +%token T_TRAIT +%token T_INTERFACE +%token T_EXTENDS +%token T_IMPLEMENTS +%token T_OBJECT_OPERATOR +%token T_DOUBLE_ARROW +%token T_LIST +%token T_ARRAY +%token T_CALLABLE +%token T_CLASS_C +%token T_TRAIT_C +%token T_METHOD_C +%token T_FUNC_C +%token T_LINE +%token T_FILE +%token T_COMMENT +%token T_DOC_COMMENT +%token T_OPEN_TAG +%token T_OPEN_TAG_WITH_ECHO +%token T_CLOSE_TAG +%token T_WHITESPACE +%token T_START_HEREDOC +%token T_END_HEREDOC +%token T_DOLLAR_OPEN_CURLY_BRACES +%token T_CURLY_OPEN +%token T_PAAMAYIM_NEKUDOTAYIM +%token T_NAMESPACE +%token T_NS_C +%token T_DIR +%token T_NS_SEPARATOR +%token T_ELLIPSIS diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Autoloader.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Autoloader.php new file mode 100644 index 0000000..809a06e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Autoloader.php @@ -0,0 +1,40 @@ +name = $name; + } + + /** + * Extends a class. + * + * @param Name|string $class Name of class to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend($class) { + $this->extends = $this->normalizeName($class); + + return $this; + } + + /** + * Implements one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to implement + * + * @return $this The builder instance (for fluid interface) + */ + public function implement() { + foreach (func_get_args() as $interface) { + $this->implements[] = $this->normalizeName($interface); + } + + return $this; + } + + /** + * Makes the class abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT); + + return $this; + } + + /** + * Makes the class final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->setModifier(Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = $this->normalizeNode($stmt); + + $targets = array( + 'Stmt_TraitUse' => &$this->uses, + 'Stmt_ClassConst' => &$this->constants, + 'Stmt_Property' => &$this->properties, + 'Stmt_ClassMethod' => &$this->methods, + ); + + $type = $stmt->getType(); + if (!isset($targets[$type])) { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $type)); + } + + $targets[$type][] = $stmt; + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Class_ The built class node + */ + public function getNode() { + return new Stmt\Class_($this->name, array( + 'flags' => $this->flags, + 'extends' => $this->extends, + 'implements' => $this->implements, + 'stmts' => array_merge($this->uses, $this->constants, $this->properties, $this->methods), + ), $this->attributes); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php new file mode 100644 index 0000000..30a1937 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php @@ -0,0 +1,42 @@ +addStmt($stmt); + } + + return $this; + } + + /** + * Sets doc comment for the declaration. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes['comments'] = array( + $this->normalizeDocComment($docComment) + ); + + return $this; + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php new file mode 100644 index 0000000..28a2ea6 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php @@ -0,0 +1,75 @@ +returnByRef = true; + + return $this; + } + + /** + * Adds a parameter. + * + * @param Node\Param|Param $param The parameter to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParam($param) { + $param = $this->normalizeNode($param); + + if (!$param instanceof Node\Param) { + throw new \LogicException(sprintf('Expected parameter node, got "%s"', $param->getType())); + } + + $this->params[] = $param; + + return $this; + } + + /** + * Adds multiple parameters. + * + * @param array $params The parameters to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addParams(array $params) { + foreach ($params as $param) { + $this->addParam($param); + } + + return $this; + } + + /** + * Sets the return type for PHP 7. + * + * @param string|Node\Name|Node\NullableType $type One of array, callable, string, int, float, bool, iterable, + * or a class/interface name. + * + * @return $this The builder instance (for fluid interface) + */ + public function setReturnType($type) + { + $this->returnType = $this->normalizeType($type); + + return $this; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php new file mode 100644 index 0000000..228bdfa --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php @@ -0,0 +1,49 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = $this->normalizeNode($stmt); + + return $this; + } + + /** + * Returns the built function node. + * + * @return Stmt\Function_ The built function node + */ + public function getNode() { + return new Stmt\Function_($this->name, array( + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + ), $this->attributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php new file mode 100644 index 0000000..8ebb292 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php @@ -0,0 +1,80 @@ +name = $name; + } + + /** + * Extends one or more interfaces. + * + * @param Name|string ...$interfaces Names of interfaces to extend + * + * @return $this The builder instance (for fluid interface) + */ + public function extend() { + foreach (func_get_args() as $interface) { + $this->extends[] = $this->normalizeName($interface); + } + + return $this; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = $this->normalizeNode($stmt); + + $type = $stmt->getType(); + switch ($type) { + case 'Stmt_ClassConst': + $this->constants[] = $stmt; + break; + + case 'Stmt_ClassMethod': + // we erase all statements in the body of an interface method + $stmt->stmts = null; + $this->methods[] = $stmt; + break; + + default: + throw new \LogicException(sprintf('Unexpected node of type "%s"', $type)); + } + + return $this; + } + + /** + * Returns the built interface node. + * + * @return Stmt\Interface_ The built interface node + */ + public function getNode() { + return new Stmt\Interface_($this->name, array( + 'extends' => $this->extends, + 'stmts' => array_merge($this->constants, $this->methods), + ), $this->attributes); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php new file mode 100644 index 0000000..1ed75ee --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php @@ -0,0 +1,128 @@ +name = $name; + } + + /** + * Makes the method public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the method protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the method private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the method static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->setModifier(Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Makes the method abstract. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeAbstract() { + if (!empty($this->stmts)) { + throw new \LogicException('Cannot make method with statements abstract'); + } + + $this->setModifier(Stmt\Class_::MODIFIER_ABSTRACT); + $this->stmts = null; // abstract methods don't have statements + + return $this; + } + + /** + * Makes the method final. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeFinal() { + $this->setModifier(Stmt\Class_::MODIFIER_FINAL); + + return $this; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + if (null === $this->stmts) { + throw new \LogicException('Cannot add statements to an abstract method'); + } + + $this->stmts[] = $this->normalizeNode($stmt); + + return $this; + } + + /** + * Returns the built method node. + * + * @return Stmt\ClassMethod The built method node + */ + public function getNode() { + return new Stmt\ClassMethod($this->name, array( + 'flags' => $this->flags, + 'byRef' => $this->returnByRef, + 'params' => $this->params, + 'returnType' => $this->returnType, + 'stmts' => $this->stmts, + ), $this->attributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php new file mode 100644 index 0000000..fe636c4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php @@ -0,0 +1,44 @@ +name = null !== $name ? $this->normalizeName($name) : null; + } + + /** + * Adds a statement. + * + * @param Node|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $this->stmts[] = $this->normalizeNode($stmt); + + return $this; + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() { + return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php new file mode 100644 index 0000000..c029e74 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php @@ -0,0 +1,91 @@ +name = $name; + } + + /** + * Sets default value for the parameter. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = $this->normalizeValue($value); + + return $this; + } + + /** + * Sets type hint for the parameter. + * + * @param string|Node\Name|Node\NullableType $type Type hint to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setTypeHint($type) { + $this->type = $this->normalizeType($type); + if ($this->type === 'void') { + throw new \LogicException('Parameter type cannot be void'); + } + + return $this; + } + + /** + * Make the parameter accept the value by reference. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeByRef() { + $this->byRef = true; + + return $this; + } + + /** + * Make the parameter variadic + * + * @return $this The builder instance (for fluid interface) + */ + public function makeVariadic() { + $this->variadic = true; + + return $this; + } + + /** + * Returns the built parameter node. + * + * @return Node\Param The built parameter node + */ + public function getNode() { + return new Node\Param( + $this->name, $this->default, $this->type, $this->byRef, $this->variadic + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php new file mode 100644 index 0000000..053c851 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php @@ -0,0 +1,111 @@ +name = $name; + } + + /** + * Makes the property public. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePublic() { + $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC); + + return $this; + } + + /** + * Makes the property protected. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeProtected() { + $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED); + + return $this; + } + + /** + * Makes the property private. + * + * @return $this The builder instance (for fluid interface) + */ + public function makePrivate() { + $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE); + + return $this; + } + + /** + * Makes the property static. + * + * @return $this The builder instance (for fluid interface) + */ + public function makeStatic() { + $this->setModifier(Stmt\Class_::MODIFIER_STATIC); + + return $this; + } + + /** + * Sets default value for the property. + * + * @param mixed $value Default value to use + * + * @return $this The builder instance (for fluid interface) + */ + public function setDefault($value) { + $this->default = $this->normalizeValue($value); + + return $this; + } + + /** + * Sets doc comment for the property. + * + * @param PhpParser\Comment\Doc|string $docComment Doc comment to set + * + * @return $this The builder instance (for fluid interface) + */ + public function setDocComment($docComment) { + $this->attributes = array( + 'comments' => array($this->normalizeDocComment($docComment)) + ); + + return $this; + } + + /** + * Returns the built class node. + * + * @return Stmt\Property The built property node + */ + public function getNode() { + return new Stmt\Property( + $this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, + array( + new Stmt\PropertyProperty($this->name, $this->default) + ), + $this->attributes + ); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php new file mode 100644 index 0000000..7b004fa --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php @@ -0,0 +1,59 @@ +name = $name; + } + + /** + * Adds a statement. + * + * @param Stmt|PhpParser\Builder $stmt The statement to add + * + * @return $this The builder instance (for fluid interface) + */ + public function addStmt($stmt) { + $stmt = $this->normalizeNode($stmt); + + if ($stmt instanceof Stmt\Property) { + $this->properties[] = $stmt; + } else if ($stmt instanceof Stmt\ClassMethod) { + $this->methods[] = $stmt; + } else if ($stmt instanceof Stmt\TraitUse) { + $this->uses[] = $stmt; + } else { + throw new \LogicException(sprintf('Unexpected node of type "%s"', $stmt->getType())); + } + + return $this; + } + + /** + * Returns the built trait node. + * + * @return Stmt\Trait_ The built interface node + */ + public function getNode() { + return new Stmt\Trait_( + $this->name, array( + 'stmts' => array_merge($this->uses, $this->properties, $this->methods) + ), $this->attributes + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php new file mode 100644 index 0000000..f6d3a85 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php @@ -0,0 +1,58 @@ +name = $this->normalizeName($name); + $this->type = $type; + } + + /** + * Sets alias for used name. + * + * @param string $alias Alias to use (last component of full name by default) + * + * @return $this The builder instance (for fluid interface) + */ + protected function as_($alias) { + $this->alias = $alias; + return $this; + } + public function __call($name, $args) { + if (method_exists($this, $name . '_')) { + return call_user_func_array(array($this, $name . '_'), $args); + } + + throw new \LogicException(sprintf('Method "%s" does not exist', $name)); + } + + /** + * Returns the built node. + * + * @return Node The built node + */ + public function getNode() { + $alias = null !== $this->alias ? $this->alias : $this->name->getLast(); + return new Stmt\Use_(array( + new Stmt\UseUse($this->name, $alias) + ), $this->type); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderAbstract.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderAbstract.php new file mode 100644 index 0000000..e353963 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderAbstract.php @@ -0,0 +1,175 @@ +getNode(); + } elseif ($node instanceof Node) { + return $node; + } + + throw new \LogicException('Expected node or builder object'); + } + + /** + * Normalizes a name: Converts plain string names to PhpParser\Node\Name. + * + * @param Name|string $name The name to normalize + * + * @return Name The normalized name + */ + protected function normalizeName($name) { + if ($name instanceof Name) { + return $name; + } elseif (is_string($name)) { + if (!$name) { + throw new \LogicException('Name cannot be empty'); + } + + if ($name[0] == '\\') { + return new Name\FullyQualified(substr($name, 1)); + } elseif (0 === strpos($name, 'namespace\\')) { + return new Name\Relative(substr($name, strlen('namespace\\'))); + } else { + return new Name($name); + } + } + + throw new \LogicException('Name must be a string or an instance of PhpParser\Node\Name'); + } + + /** + * Normalizes a type: Converts plain-text type names into proper AST representation. + * + * In particular, builtin types are left as strings, custom types become Names and nullables + * are wrapped in NullableType nodes. + * + * @param Name|string|NullableType $type The type to normalize + * + * @return Name|string|NullableType The normalized type + */ + protected function normalizeType($type) { + if (!is_string($type)) { + if (!$type instanceof Name && !$type instanceof NullableType) { + throw new \LogicException( + 'Type must be a string, or an instance of Name or NullableType'); + } + return $type; + } + + $nullable = false; + if (strlen($type) > 0 && $type[0] === '?') { + $nullable = true; + $type = substr($type, 1); + } + + $builtinTypes = array( + 'array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object' + ); + + $lowerType = strtolower($type); + if (in_array($lowerType, $builtinTypes)) { + $type = $lowerType; + } else { + $type = $this->normalizeName($type); + } + + if ($nullable && $type === 'void') { + throw new \LogicException('void type cannot be nullable'); + } + + return $nullable ? new Node\NullableType($type) : $type; + } + + /** + * Normalizes a value: Converts nulls, booleans, integers, + * floats, strings and arrays into their respective nodes + * + * @param mixed $value The value to normalize + * + * @return Expr The normalized value + */ + protected function normalizeValue($value) { + if ($value instanceof Node) { + return $value; + } elseif (is_null($value)) { + return new Expr\ConstFetch( + new Name('null') + ); + } elseif (is_bool($value)) { + return new Expr\ConstFetch( + new Name($value ? 'true' : 'false') + ); + } elseif (is_int($value)) { + return new Scalar\LNumber($value); + } elseif (is_float($value)) { + return new Scalar\DNumber($value); + } elseif (is_string($value)) { + return new Scalar\String_($value); + } elseif (is_array($value)) { + $items = array(); + $lastKey = -1; + foreach ($value as $itemKey => $itemValue) { + // for consecutive, numeric keys don't generate keys + if (null !== $lastKey && ++$lastKey === $itemKey) { + $items[] = new Expr\ArrayItem( + $this->normalizeValue($itemValue) + ); + } else { + $lastKey = null; + $items[] = new Expr\ArrayItem( + $this->normalizeValue($itemValue), + $this->normalizeValue($itemKey) + ); + } + } + + return new Expr\Array_($items); + } else { + throw new \LogicException('Invalid value'); + } + } + + /** + * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc. + * + * @param Comment\Doc|string $docComment The doc comment to normalize + * + * @return Comment\Doc The normalized doc comment + */ + protected function normalizeDocComment($docComment) { + if ($docComment instanceof Comment\Doc) { + return $docComment; + } else if (is_string($docComment)) { + return new Comment\Doc($docComment); + } else { + throw new \LogicException('Doc comment must be a string or an instance of PhpParser\Comment\Doc'); + } + } + + /** + * Sets a modifier in the $this->type property. + * + * @param int $modifier Modifier to set + */ + protected function setModifier($modifier) { + Stmt\Class_::verifyModifier($this->flags, $modifier); + $this->flags |= $modifier; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php new file mode 100644 index 0000000..42c7f61 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php @@ -0,0 +1,127 @@ +text = $text; + $this->line = $startLine; + $this->filePos = $startFilePos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function getText() { + return $this->text; + } + + /** + * Gets the line number the comment started on. + * + * @return int Line number + */ + public function getLine() { + return $this->line; + } + + /** + * Gets the file offset the comment started on. + * + * @return int File offset + */ + public function getFilePos() { + return $this->filePos; + } + + /** + * Gets the comment text. + * + * @return string The comment text (including comment delimiters like /*) + */ + public function __toString() { + return $this->text; + } + + /** + * Gets the reformatted comment text. + * + * "Reformatted" here means that we try to clean up the whitespace at the + * starts of the lines. This is necessary because we receive the comments + * without trailing whitespace on the first line, but with trailing whitespace + * on all subsequent lines. + * + * @return mixed|string + */ + public function getReformattedText() { + $text = trim($this->text); + $newlinePos = strpos($text, "\n"); + if (false === $newlinePos) { + // Single line comments don't need further processing + return $text; + } elseif (preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\R\s+\*.*)+$)', $text)) { + // Multi line comment of the type + // + // /* + // * Some text. + // * Some more text. + // */ + // + // is handled by replacing the whitespace sequences before the * by a single space + return preg_replace('(^\s+\*)m', ' *', $this->text); + } elseif (preg_match('(^/\*\*?\s*[\r\n])', $text) && preg_match('(\n(\s*)\*/$)', $text, $matches)) { + // Multi line comment of the type + // + // /* + // Some text. + // Some more text. + // */ + // + // is handled by removing the whitespace sequence on the line before the closing + // */ on all lines. So if the last line is " */", then " " is removed at the + // start of all lines. + return preg_replace('(^' . preg_quote($matches[1]) . ')m', '', $text); + } elseif (preg_match('(^/\*\*?\s*(?!\s))', $text, $matches)) { + // Multi line comment of the type + // + // /* Some text. + // Some more text. + // Indented text. + // Even more text. */ + // + // is handled by removing the difference between the shortest whitespace prefix on all + // lines and the length of the "/* " opening sequence. + $prefixLen = $this->getShortestWhitespacePrefixLen(substr($text, $newlinePos + 1)); + $removeLen = $prefixLen - strlen($matches[0]); + return preg_replace('(^\s{' . $removeLen . '})m', '', $text); + } + + // No idea how to format this comment, so simply return as is + return $text; + } + + private function getShortestWhitespacePrefixLen($str) { + $lines = explode("\n", $str); + $shortestPrefixLen = INF; + foreach ($lines as $line) { + preg_match('(^\s*)', $line, $matches); + $prefixLen = strlen($matches[0]); + if ($prefixLen < $shortestPrefixLen) { + $shortestPrefixLen = $prefixLen; + } + } + return $shortestPrefixLen; + } + + public function jsonSerialize() { + // Technically not a node, but we make it look like one anyway + $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment'; + return [ + 'nodeType' => $type, + 'text' => $this->text, + 'line' => $this->line, + 'filePos' => $this->filePos, + ]; + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php new file mode 100644 index 0000000..24fc6c9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php @@ -0,0 +1,7 @@ +rawMessage = (string) $message; + if (is_array($attributes)) { + $this->attributes = $attributes; + } else { + $this->attributes = array('startLine' => $attributes); + } + $this->updateMessage(); + } + + /** + * Gets the error message + * + * @return string Error message + */ + public function getRawMessage() { + return $this->rawMessage; + } + + /** + * Gets the line the error starts in. + * + * @return int Error start line + */ + public function getStartLine() { + return isset($this->attributes['startLine']) ? $this->attributes['startLine'] : -1; + } + + /** + * Gets the line the error ends in. + * + * @return int Error end line + */ + public function getEndLine() { + return isset($this->attributes['endLine']) ? $this->attributes['endLine'] : -1; + } + + + /** + * Gets the attributes of the node/token the error occurred at. + * + * @return array + */ + public function getAttributes() { + return $this->attributes; + } + + /** + * Sets the attributes of the node/token the error occured at. + * + * @param array $attributes + */ + public function setAttributes(array $attributes) { + $this->attributes = $attributes; + $this->updateMessage(); + } + + /** + * Sets the line of the PHP file the error occurred in. + * + * @param string $message Error message + */ + public function setRawMessage($message) { + $this->rawMessage = (string) $message; + $this->updateMessage(); + } + + /** + * Sets the line the error starts in. + * + * @param int $line Error start line + */ + public function setStartLine($line) { + $this->attributes['startLine'] = (int) $line; + $this->updateMessage(); + } + + /** + * Returns whether the error has start and end column information. + * + * For column information enable the startFilePos and endFilePos in the lexer options. + * + * @return bool + */ + public function hasColumnInfo() { + return isset($this->attributes['startFilePos']) && isset($this->attributes['endFilePos']); + } + + /** + * Gets the start column (1-based) into the line where the error started. + * + * @param string $code Source code of the file + * @return int + */ + public function getStartColumn($code) { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['startFilePos']); + } + + /** + * Gets the end column (1-based) into the line where the error ended. + * + * @param string $code Source code of the file + * @return int + */ + public function getEndColumn($code) { + if (!$this->hasColumnInfo()) { + throw new \RuntimeException('Error does not have column information'); + } + + return $this->toColumn($code, $this->attributes['endFilePos']); + } + + public function getMessageWithColumnInfo($code) { + return sprintf( + '%s from %d:%d to %d:%d', $this->getRawMessage(), + $this->getStartLine(), $this->getStartColumn($code), + $this->getEndLine(), $this->getEndColumn($code) + ); + } + + private function toColumn($code, $pos) { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } + + /** + * Updates the exception message after a change to rawMessage or rawLine. + */ + protected function updateMessage() { + $this->message = $this->rawMessage; + + if (-1 === $this->getStartLine()) { + $this->message .= ' on unknown line'; + } else { + $this->message .= ' on line ' . $this->getStartLine(); + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php new file mode 100644 index 0000000..fa2c2f8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php @@ -0,0 +1,13 @@ +errors[] = $error; + } + + /** + * Get collected errors. + * + * @return Error[] + */ + public function getErrors() { + return $this->errors; + } + + /** + * Check whether there are any errors. + * + * @return bool + */ + public function hasErrors() { + return !empty($this->errors); + } + + /** + * Reset/clear collected errors. + */ + public function clearErrors() { + $this->errors = []; + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php new file mode 100644 index 0000000..c5a76dd --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php @@ -0,0 +1,18 @@ +tokenMap = $this->createTokenMap(); + + // map of tokens to drop while lexing (the map is only used for isset lookup, + // that's why the value is simply set to 1; the value is never actually used.) + $this->dropTokens = array_fill_keys( + array(T_WHITESPACE, T_OPEN_TAG, T_COMMENT, T_DOC_COMMENT), 1 + ); + + // the usedAttributes member is a map of the used attribute names to a dummy + // value (here "true") + $options += array( + 'usedAttributes' => array('comments', 'startLine', 'endLine'), + ); + $this->usedAttributes = array_fill_keys($options['usedAttributes'], true); + } + + /** + * Initializes the lexer for lexing the provided source code. + * + * This function does not throw if lexing errors occur. Instead, errors may be retrieved using + * the getErrors() method. + * + * @param string $code The source code to lex + * @param ErrorHandler|null $errorHandler Error handler to use for lexing errors. Defaults to + * ErrorHandler\Throwing + */ + public function startLexing($code, ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing(); + } + + $this->code = $code; // keep the code around for __halt_compiler() handling + $this->pos = -1; + $this->line = 1; + $this->filePos = 0; + + // If inline HTML occurs without preceding code, treat it as if it had a leading newline. + // This ensures proper composability, because having a newline is the "safe" assumption. + $this->prevCloseTagHasNewline = true; + + $scream = ini_set('xdebug.scream', '0'); + + $this->resetErrors(); + $this->tokens = @token_get_all($code); + $this->handleErrors($errorHandler); + + if (false !== $scream) { + ini_set('xdebug.scream', $scream); + } + } + + protected function resetErrors() { + if (function_exists('error_clear_last')) { + error_clear_last(); + } else { + // set error_get_last() to defined state by forcing an undefined variable error + set_error_handler(function() { return false; }, 0); + @$undefinedVariable; + restore_error_handler(); + } + } + + private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler) { + for ($i = $start; $i < $end; $i++) { + $chr = $this->code[$i]; + if ($chr === 'b' || $chr === 'B') { + // HHVM does not treat b" tokens correctly, so ignore these + continue; + } + + if ($chr === "\0") { + // PHP cuts error message after null byte, so need special case + $errorMsg = 'Unexpected null byte'; + } else { + $errorMsg = sprintf( + 'Unexpected character "%s" (ASCII %d)', $chr, ord($chr) + ); + } + + $errorHandler->handleError(new Error($errorMsg, [ + 'startLine' => $line, + 'endLine' => $line, + 'startFilePos' => $i, + 'endFilePos' => $i, + ])); + } + } + + private function isUnterminatedComment($token) { + return ($token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT) + && substr($token[1], 0, 2) === '/*' + && substr($token[1], -2) !== '*/'; + } + + private function errorMayHaveOccurred() { + if (defined('HHVM_VERSION')) { + // In HHVM token_get_all() does not throw warnings, so we need to conservatively + // assume that an error occurred + return true; + } + + $error = error_get_last(); + return null !== $error + && false === strpos($error['message'], 'Undefined variable'); + } + + protected function handleErrors(ErrorHandler $errorHandler) { + if (!$this->errorMayHaveOccurred()) { + return; + } + + // PHP's error handling for token_get_all() is rather bad, so if we want detailed + // error information we need to compute it ourselves. Invalid character errors are + // detected by finding "gaps" in the token array. Unterminated comments are detected + // by checking if a trailing comment has a "*/" at the end. + + $filePos = 0; + $line = 1; + foreach ($this->tokens as $i => $token) { + $tokenValue = \is_string($token) ? $token : $token[1]; + $tokenLen = \strlen($tokenValue); + + if (substr($this->code, $filePos, $tokenLen) !== $tokenValue) { + // Something is missing, must be an invalid character + $nextFilePos = strpos($this->code, $tokenValue, $filePos); + $this->handleInvalidCharacterRange( + $filePos, $nextFilePos, $line, $errorHandler); + $filePos = $nextFilePos; + } + + $filePos += $tokenLen; + $line += substr_count($tokenValue, "\n"); + } + + if ($filePos !== \strlen($this->code)) { + if (substr($this->code, $filePos, 2) === '/*') { + // Unlike PHP, HHVM will drop unterminated comments entirely + $comment = substr($this->code, $filePos); + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line, + 'endLine' => $line + substr_count($comment, "\n"), + 'startFilePos' => $filePos, + 'endFilePos' => $filePos + \strlen($comment), + ])); + + // Emulate the PHP behavior + $isDocComment = isset($comment[3]) && $comment[3] === '*'; + $this->tokens[] = [$isDocComment ? T_DOC_COMMENT : T_COMMENT, $comment, $line]; + } else { + // Invalid characters at the end of the input + $this->handleInvalidCharacterRange( + $filePos, \strlen($this->code), $line, $errorHandler); + } + return; + } + + if (count($this->tokens) > 0) { + // Check for unterminated comment + $lastToken = $this->tokens[count($this->tokens) - 1]; + if ($this->isUnterminatedComment($lastToken)) { + $errorHandler->handleError(new Error('Unterminated comment', [ + 'startLine' => $line - substr_count($lastToken[1], "\n"), + 'endLine' => $line, + 'startFilePos' => $filePos - \strlen($lastToken[1]), + 'endFilePos' => $filePos, + ])); + } + } + } + + /** + * Fetches the next token. + * + * The available attributes are determined by the 'usedAttributes' option, which can + * be specified in the constructor. The following attributes are supported: + * + * * 'comments' => Array of PhpParser\Comment or PhpParser\Comment\Doc instances, + * representing all comments that occurred between the previous + * non-discarded token and the current one. + * * 'startLine' => Line in which the node starts. + * * 'endLine' => Line in which the node ends. + * * 'startTokenPos' => Offset into the token array of the first token in the node. + * * 'endTokenPos' => Offset into the token array of the last token in the node. + * * 'startFilePos' => Offset into the code string of the first character that is part of the node. + * * 'endFilePos' => Offset into the code string of the last character that is part of the node. + * + * @param mixed $value Variable to store token content in + * @param mixed $startAttributes Variable to store start attributes in + * @param mixed $endAttributes Variable to store end attributes in + * + * @return int Token id + */ + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { + $startAttributes = array(); + $endAttributes = array(); + + while (1) { + if (isset($this->tokens[++$this->pos])) { + $token = $this->tokens[$this->pos]; + } else { + // EOF token with ID 0 + $token = "\0"; + } + + if (isset($this->usedAttributes['startLine'])) { + $startAttributes['startLine'] = $this->line; + } + if (isset($this->usedAttributes['startTokenPos'])) { + $startAttributes['startTokenPos'] = $this->pos; + } + if (isset($this->usedAttributes['startFilePos'])) { + $startAttributes['startFilePos'] = $this->filePos; + } + + if (\is_string($token)) { + $value = $token; + if (isset($token[1])) { + // bug in token_get_all + $this->filePos += 2; + $id = ord('"'); + } else { + $this->filePos += 1; + $id = ord($token); + } + } elseif (!isset($this->dropTokens[$token[0]])) { + $value = $token[1]; + $id = $this->tokenMap[$token[0]]; + if (T_CLOSE_TAG === $token[0]) { + $this->prevCloseTagHasNewline = false !== strpos($token[1], "\n"); + } else if (T_INLINE_HTML === $token[0]) { + $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline; + } + + $this->line += substr_count($value, "\n"); + $this->filePos += \strlen($value); + } else { + if (T_COMMENT === $token[0] || T_DOC_COMMENT === $token[0]) { + if (isset($this->usedAttributes['comments'])) { + $comment = T_DOC_COMMENT === $token[0] + ? new Comment\Doc($token[1], $this->line, $this->filePos) + : new Comment($token[1], $this->line, $this->filePos); + $startAttributes['comments'][] = $comment; + } + } + + $this->line += substr_count($token[1], "\n"); + $this->filePos += \strlen($token[1]); + continue; + } + + if (isset($this->usedAttributes['endLine'])) { + $endAttributes['endLine'] = $this->line; + } + if (isset($this->usedAttributes['endTokenPos'])) { + $endAttributes['endTokenPos'] = $this->pos; + } + if (isset($this->usedAttributes['endFilePos'])) { + $endAttributes['endFilePos'] = $this->filePos - 1; + } + + return $id; + } + + throw new \RuntimeException('Reached end of lexer loop'); + } + + /** + * Returns the token array for current code. + * + * The token array is in the same format as provided by the + * token_get_all() function and does not discard tokens (i.e. + * whitespace and comments are included). The token position + * attributes are against this token array. + * + * @return array Array of tokens in token_get_all() format + */ + public function getTokens() { + return $this->tokens; + } + + /** + * Handles __halt_compiler() by returning the text after it. + * + * @return string Remaining text + */ + public function handleHaltCompiler() { + // text after T_HALT_COMPILER, still including (); + $textAfter = substr($this->code, $this->filePos); + + // ensure that it is followed by (); + // this simplifies the situation, by not allowing any comments + // in between of the tokens. + if (!preg_match('~^\s*\(\s*\)\s*(?:;|\?>\r?\n?)~', $textAfter, $matches)) { + throw new Error('__HALT_COMPILER must be followed by "();"'); + } + + // prevent the lexer from returning any further tokens + $this->pos = count($this->tokens); + + // return with (); removed + return (string) substr($textAfter, strlen($matches[0])); // (string) converts false to '' + } + + /** + * Creates the token map. + * + * The token map maps the PHP internal token identifiers + * to the identifiers used by the Parser. Additionally it + * maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'. + * + * @return array The token map + */ + protected function createTokenMap() { + $tokenMap = array(); + + // 256 is the minimum possible token number, as everything below + // it is an ASCII value + for ($i = 256; $i < 1000; ++$i) { + if (T_DOUBLE_COLON === $i) { + // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM + $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM; + } elseif(T_OPEN_TAG_WITH_ECHO === $i) { + // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO + $tokenMap[$i] = Tokens::T_ECHO; + } elseif(T_CLOSE_TAG === $i) { + // T_CLOSE_TAG is equivalent to ';' + $tokenMap[$i] = ord(';'); + } elseif ('UNKNOWN' !== $name = token_name($i)) { + if ('T_HASHBANG' === $name) { + // HHVM uses a special token for #! hashbang lines + $tokenMap[$i] = Tokens::T_INLINE_HTML; + } else if (defined($name = Tokens::class . '::' . $name)) { + // Other tokens can be mapped directly + $tokenMap[$i] = constant($name); + } + } + } + + // HHVM uses a special token for numbers that overflow to double + if (defined('T_ONUMBER')) { + $tokenMap[T_ONUMBER] = Tokens::T_DNUMBER; + } + // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant + if (defined('T_COMPILER_HALT_OFFSET')) { + $tokenMap[T_COMPILER_HALT_OFFSET] = Tokens::T_STRING; + } + + return $tokenMap; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php new file mode 100644 index 0000000..739a328 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php @@ -0,0 +1,174 @@ +newKeywords = array(); + foreach ($newKeywordsPerVersion as $version => $newKeywords) { + if (version_compare(PHP_VERSION, $version, '>=')) { + break; + } + + $this->newKeywords += $newKeywords; + } + + if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) { + return; + } + $this->tokenMap[self::T_COALESCE] = Tokens::T_COALESCE; + $this->tokenMap[self::T_SPACESHIP] = Tokens::T_SPACESHIP; + $this->tokenMap[self::T_YIELD_FROM] = Tokens::T_YIELD_FROM; + + if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) { + return; + } + $this->tokenMap[self::T_ELLIPSIS] = Tokens::T_ELLIPSIS; + $this->tokenMap[self::T_POW] = Tokens::T_POW; + $this->tokenMap[self::T_POW_EQUAL] = Tokens::T_POW_EQUAL; + } + + public function startLexing($code, ErrorHandler $errorHandler = null) { + $this->inObjectAccess = false; + + parent::startLexing($code, $errorHandler); + if ($this->requiresEmulation($code)) { + $this->emulateTokens(); + } + } + + /* + * Checks if the code is potentially using features that require emulation. + */ + protected function requiresEmulation($code) { + if (version_compare(PHP_VERSION, self::PHP_7_0, '>=')) { + return false; + } + + if (preg_match('(\?\?|<=>|yield[ \n\r\t]+from)', $code)) { + return true; + } + + if (version_compare(PHP_VERSION, self::PHP_5_6, '>=')) { + return false; + } + + return preg_match('(\.\.\.|(?tokens); $i < $c; ++$i) { + $replace = null; + if (isset($this->tokens[$i + 1])) { + if ($this->tokens[$i] === '?' && $this->tokens[$i + 1] === '?') { + array_splice($this->tokens, $i, 2, array( + array(self::T_COALESCE, '??', $line) + )); + $c--; + continue; + } + if ($this->tokens[$i][0] === T_IS_SMALLER_OR_EQUAL + && $this->tokens[$i + 1] === '>' + ) { + array_splice($this->tokens, $i, 2, array( + array(self::T_SPACESHIP, '<=>', $line) + )); + $c--; + continue; + } + if ($this->tokens[$i] === '*' && $this->tokens[$i + 1] === '*') { + array_splice($this->tokens, $i, 2, array( + array(self::T_POW, '**', $line) + )); + $c--; + continue; + } + if ($this->tokens[$i] === '*' && $this->tokens[$i + 1][0] === T_MUL_EQUAL) { + array_splice($this->tokens, $i, 2, array( + array(self::T_POW_EQUAL, '**=', $line) + )); + $c--; + continue; + } + } + + if (isset($this->tokens[$i + 2])) { + if ($this->tokens[$i][0] === T_YIELD && $this->tokens[$i + 1][0] === T_WHITESPACE + && $this->tokens[$i + 2][0] === T_STRING + && !strcasecmp($this->tokens[$i + 2][1], 'from') + ) { + array_splice($this->tokens, $i, 3, array( + array( + self::T_YIELD_FROM, + $this->tokens[$i][1] . $this->tokens[$i + 1][1] . $this->tokens[$i + 2][1], + $line + ) + )); + $c -= 2; + $line += substr_count($this->tokens[$i][1], "\n"); + continue; + } + if ($this->tokens[$i] === '.' && $this->tokens[$i + 1] === '.' + && $this->tokens[$i + 2] === '.' + ) { + array_splice($this->tokens, $i, 3, array( + array(self::T_ELLIPSIS, '...', $line) + )); + $c -= 2; + continue; + } + } + + if (\is_array($this->tokens[$i])) { + $line += substr_count($this->tokens[$i][1], "\n"); + } + } + } + + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { + $token = parent::getNextToken($value, $startAttributes, $endAttributes); + + // replace new keywords by their respective tokens. This is not done + // if we currently are in an object access (e.g. in $obj->namespace + // "namespace" stays a T_STRING tokens and isn't converted to T_NAMESPACE) + if (Tokens::T_STRING === $token && !$this->inObjectAccess) { + if (isset($this->newKeywords[strtolower($value)])) { + return $this->newKeywords[strtolower($value)]; + } + } else { + // keep track of whether we currently are in an object access (after ->) + $this->inObjectAccess = Tokens::T_OBJECT_OPERATOR === $token; + } + + return $token; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node.php new file mode 100644 index 0000000..6925fd7 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node.php @@ -0,0 +1,88 @@ +value = $value; + $this->byRef = $byRef; + $this->unpack = $unpack; + } + + public function getSubNodeNames() { + return array('value', 'byRef', 'unpack'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php new file mode 100644 index 0000000..26322d4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php @@ -0,0 +1,30 @@ +name = $name; + $this->value = $value; + } + + public function getSubNodeNames() { + return array('name', 'value'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php new file mode 100644 index 0000000..2dae5bf --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php @@ -0,0 +1,9 @@ +var = $var; + $this->dim = $dim; + } + + public function getSubNodeNames() { + return array('var', 'dim'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php new file mode 100644 index 0000000..de73ef4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php @@ -0,0 +1,34 @@ +key = $key; + $this->value = $value; + $this->byRef = $byRef; + } + + public function getSubNodeNames() { + return array('key', 'value', 'byRef'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php new file mode 100644 index 0000000..9151f27 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php @@ -0,0 +1,30 @@ +items = $items; + } + + public function getSubNodeNames() { + return array('items'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php new file mode 100644 index 0000000..1f280ff --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php @@ -0,0 +1,30 @@ +var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() { + return array('var', 'expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php new file mode 100644 index 0000000..83540a0 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php @@ -0,0 +1,30 @@ +var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() { + return array('var', 'expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php new file mode 100644 index 0000000..9e3ed82 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php @@ -0,0 +1,9 @@ +var = $var; + $this->expr = $expr; + } + + public function getSubNodeNames() { + return array('var', 'expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php new file mode 100644 index 0000000..6f87e23 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php @@ -0,0 +1,30 @@ +left = $left; + $this->right = $right; + } + + public function getSubNodeNames() { + return array('left', 'right'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php new file mode 100644 index 0000000..bd6c5c1 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php @@ -0,0 +1,9 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php new file mode 100644 index 0000000..8f543b8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php new file mode 100644 index 0000000..bf850dc --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php new file mode 100644 index 0000000..08b3a38 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php @@ -0,0 +1,9 @@ +class = $class; + $this->name = $name; + } + + public function getSubNodeNames() { + return array('class', 'name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php new file mode 100644 index 0000000..198ec4d --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php new file mode 100644 index 0000000..5d37655 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php @@ -0,0 +1,65 @@ + false : Whether the closure is static + * 'byRef' => false : Whether to return by reference + * 'params' => array(): Parameters + * 'uses' => array(): use()s + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->static = isset($subNodes['static']) ? $subNodes['static'] : false; + $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; + $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); + $this->uses = isset($subNodes['uses']) ? $subNodes['uses'] : array(); + $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('static', 'byRef', 'params', 'uses', 'returnType', 'stmts'); + } + + public function returnsByRef() { + return $this->byRef; + } + + public function getParams() { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getStmts() { + return $this->stmts; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php new file mode 100644 index 0000000..f4d0202 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php @@ -0,0 +1,30 @@ +var = $var; + $this->byRef = $byRef; + } + + public function getSubNodeNames() { + return array('var', 'byRef'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php new file mode 100644 index 0000000..98e51d5 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php @@ -0,0 +1,27 @@ +name = $name; + } + + public function getSubNodeNames() { + return array('name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php new file mode 100644 index 0000000..0c0509e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php new file mode 100644 index 0000000..5ab8fd4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php @@ -0,0 +1,27 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php new file mode 100644 index 0000000..eadffd0 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php new file mode 100644 index 0000000..b0b94cf --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php @@ -0,0 +1,30 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php new file mode 100644 index 0000000..60d0050 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php @@ -0,0 +1,31 @@ +name = $name; + $this->args = $args; + } + + public function getSubNodeNames() { + return array('name', 'args'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php new file mode 100644 index 0000000..b27f3af --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php @@ -0,0 +1,35 @@ +expr = $expr; + $this->type = $type; + } + + public function getSubNodeNames() { + return array('expr', 'type'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php new file mode 100644 index 0000000..69573d8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php @@ -0,0 +1,31 @@ +expr = $expr; + $this->class = $class; + } + + public function getSubNodeNames() { + return array('expr', 'class'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php new file mode 100644 index 0000000..4ec1d02 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php @@ -0,0 +1,26 @@ +vars = $vars; + } + + public function getSubNodeNames() { + return array('vars'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php new file mode 100644 index 0000000..30f3dc1 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php @@ -0,0 +1,26 @@ +items = $items; + } + + public function getSubNodeNames() { + return array('items'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php new file mode 100644 index 0000000..a6cdd07 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php @@ -0,0 +1,35 @@ +var = $var; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() { + return array('var', 'name', 'args'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php new file mode 100644 index 0000000..a8c8779 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php @@ -0,0 +1,31 @@ +class = $class; + $this->args = $args; + } + + public function getSubNodeNames() { + return array('class', 'args'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php new file mode 100644 index 0000000..06ce547 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php @@ -0,0 +1,26 @@ +var = $var; + } + + public function getSubNodeNames() { + return array('var'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php new file mode 100644 index 0000000..54865ba --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php @@ -0,0 +1,26 @@ +var = $var; + } + + public function getSubNodeNames() { + return array('var'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php new file mode 100644 index 0000000..db30f51 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php @@ -0,0 +1,26 @@ +var = $var; + } + + public function getSubNodeNames() { + return array('var'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php new file mode 100644 index 0000000..0635602 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php @@ -0,0 +1,26 @@ +var = $var; + } + + public function getSubNodeNames() { + return array('var'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php new file mode 100644 index 0000000..0666ab8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php new file mode 100644 index 0000000..adcf21c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php @@ -0,0 +1,30 @@ +var = $var; + $this->name = $name; + } + + public function getSubNodeNames() { + return array('var', 'name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php new file mode 100644 index 0000000..9516a32 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php @@ -0,0 +1,26 @@ +parts = $parts; + } + + public function getSubNodeNames() { + return array('parts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php new file mode 100644 index 0000000..5118f34 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php @@ -0,0 +1,35 @@ +class = $class; + $this->name = $name; + $this->args = $args; + } + + public function getSubNodeNames() { + return array('class', 'name', 'args'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php new file mode 100644 index 0000000..477a69d --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php @@ -0,0 +1,31 @@ +class = $class; + $this->name = $name; + } + + public function getSubNodeNames() { + return array('class', 'name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php new file mode 100644 index 0000000..5730139 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php @@ -0,0 +1,34 @@ +cond = $cond; + $this->if = $if; + $this->else = $else; + } + + public function getSubNodeNames() { + return array('cond', 'if', 'else'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php new file mode 100644 index 0000000..94635d6 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php new file mode 100644 index 0000000..6514120 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php new file mode 100644 index 0000000..3ae3ecd --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php @@ -0,0 +1,26 @@ +name = $name; + } + + public function getSubNodeNames() { + return array('name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php new file mode 100644 index 0000000..993c82c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php new file mode 100644 index 0000000..f3ca88e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php @@ -0,0 +1,30 @@ +key = $key; + $this->value = $value; + } + + public function getSubNodeNames() { + return array('key', 'value'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php new file mode 100644 index 0000000..8256945 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php @@ -0,0 +1,36 @@ +parts = self::prepareName($name); + } + + public function getSubNodeNames() { + return array('parts'); + } + + /** + * Gets the first part of the name, i.e. everything before the first namespace separator. + * + * @return string First part of the name + */ + public function getFirst() { + return $this->parts[0]; + } + + /** + * Gets the last part of the name, i.e. everything after the last namespace separator. + * + * @return string Last part of the name + */ + public function getLast() { + return $this->parts[count($this->parts) - 1]; + } + + /** + * Checks whether the name is unqualified. (E.g. Name) + * + * @return bool Whether the name is unqualified + */ + public function isUnqualified() { + return 1 == count($this->parts); + } + + /** + * Checks whether the name is qualified. (E.g. Name\Name) + * + * @return bool Whether the name is qualified + */ + public function isQualified() { + return 1 < count($this->parts); + } + + /** + * Checks whether the name is fully qualified. (E.g. \Name) + * + * @return bool Whether the name is fully qualified + */ + public function isFullyQualified() { + return false; + } + + /** + * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name) + * + * @return bool Whether the name is relative + */ + public function isRelative() { + return false; + } + + /** + * Returns a string representation of the name by imploding the namespace parts with the + * namespace separator. + * + * @return string String representation + */ + public function toString() { + return implode('\\', $this->parts); + } + + /** + * Returns a string representation of the name by imploding the namespace parts with the + * namespace separator. + * + * @return string String representation + */ + public function __toString() { + return implode('\\', $this->parts); + } + + /** + * Gets a slice of a name (similar to array_slice). + * + * This method returns a new instance of the same type as the original and with the same + * attributes. + * + * If the slice is empty, null is returned. The null value will be correctly handled in + * concatenations using concat(). + * + * Offset and length have the same meaning as in array_slice(). + * + * @param int $offset Offset to start the slice at (may be negative) + * @param int|null $length Length of the slice (may be negative) + * + * @return static|null Sliced name + */ + public function slice($offset, $length = null) { + $numParts = count($this->parts); + + $realOffset = $offset < 0 ? $offset + $numParts : $offset; + if ($realOffset < 0 || $realOffset > $numParts) { + throw new \OutOfBoundsException(sprintf('Offset %d is out of bounds', $offset)); + } + + if (null === $length) { + $realLength = $numParts - $realOffset; + } else { + $realLength = $length < 0 ? $length + $numParts - $realOffset : $length; + if ($realLength < 0 || $realLength > $numParts) { + throw new \OutOfBoundsException(sprintf('Length %d is out of bounds', $length)); + } + } + + if ($realLength === 0) { + // Empty slice is represented as null + return null; + } + + return new static(array_slice($this->parts, $realOffset, $realLength), $this->attributes); + } + + /** + * Concatenate two names, yielding a new Name instance. + * + * The type of the generated instance depends on which class this method is called on, for + * example Name\FullyQualified::concat() will yield a Name\FullyQualified instance. + * + * If one of the arguments is null, a new instance of the other name will be returned. If both + * arguments are null, null will be returned. As such, writing + * Name::concat($namespace, $shortName) + * where $namespace is a Name node or null will work as expected. + * + * @param string|array|self|null $name1 The first name + * @param string|array|self|null $name2 The second name + * @param array $attributes Attributes to assign to concatenated name + * + * @return static|null Concatenated name + */ + public static function concat($name1, $name2, array $attributes = []) { + if (null === $name1 && null === $name2) { + return null; + } elseif (null === $name1) { + return new static(self::prepareName($name2), $attributes); + } else if (null === $name2) { + return new static(self::prepareName($name1), $attributes); + } else { + return new static( + array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes + ); + } + } + + /** + * Prepares a (string, array or Name node) name for use in name changing methods by converting + * it to an array. + * + * @param string|array|self $name Name to prepare + * + * @return array Prepared name + */ + private static function prepareName($name) { + if (\is_string($name)) { + return explode('\\', $name); + } elseif (\is_array($name)) { + return $name; + } elseif ($name instanceof self) { + return $name->parts; + } + + throw new \InvalidArgumentException( + 'Expected string, array of parts or Name instance' + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php new file mode 100644 index 0000000..97cc111 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php @@ -0,0 +1,42 @@ +type = $type; + } + + public function getSubNodeNames() { + return array('type'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php new file mode 100644 index 0000000..b35ee4e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php @@ -0,0 +1,42 @@ +type = $type; + $this->byRef = $byRef; + $this->variadic = $variadic; + $this->name = $name; + $this->default = $default; + } + + public function getSubNodeNames() { + return array('type', 'byRef', 'variadic', 'name', 'default'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php new file mode 100644 index 0000000..0117753 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php @@ -0,0 +1,7 @@ +value = $value; + } + + public function getSubNodeNames() { + return array('value'); + } + + /** + * @internal + * + * Parses a DNUMBER token like PHP would. + * + * @param string $str A string number + * + * @return float The parsed number + */ + public static function parse($str) { + // if string contains any of .eE just cast it to float + if (false !== strpbrk($str, '.eE')) { + return (float) $str; + } + + // otherwise it's an integer notation that overflowed into a float + // if it starts with 0 it's one of the special integer notations + if ('0' === $str[0]) { + // hex + if ('x' === $str[1] || 'X' === $str[1]) { + return hexdec($str); + } + + // bin + if ('b' === $str[1] || 'B' === $str[1]) { + return bindec($str); + } + + // oct + // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9) + // so that only the digits before that are used + return octdec(substr($str, 0, strcspn($str, '89'))); + } + + // dec + return (float) $str; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php new file mode 100644 index 0000000..4f9b433 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php @@ -0,0 +1,27 @@ +parts = $parts; + } + + public function getSubNodeNames() { + return array('parts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php new file mode 100644 index 0000000..50cb1af --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php @@ -0,0 +1,26 @@ +value = $value; + } + + public function getSubNodeNames() { + return array('value'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php new file mode 100644 index 0000000..3559b98 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/LNumber.php @@ -0,0 +1,67 @@ +value = $value; + } + + public function getSubNodeNames() { + return array('value'); + } + + /** + * Constructs an LNumber node from a string number literal. + * + * @param string $str String number literal (decimal, octal, hex or binary) + * @param array $attributes Additional attributes + * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5) + * + * @return LNumber The constructed LNumber, including kind attribute + */ + public static function fromString($str, array $attributes = array(), $allowInvalidOctal = false) { + if ('0' !== $str[0] || '0' === $str) { + $attributes['kind'] = LNumber::KIND_DEC; + return new LNumber((int) $str, $attributes); + } + + if ('x' === $str[1] || 'X' === $str[1]) { + $attributes['kind'] = LNumber::KIND_HEX; + return new LNumber(hexdec($str), $attributes); + } + + if ('b' === $str[1] || 'B' === $str[1]) { + $attributes['kind'] = LNumber::KIND_BIN; + return new LNumber(bindec($str), $attributes); + } + + if (!$allowInvalidOctal && strpbrk($str, '89')) { + throw new Error('Invalid numeric literal', $attributes); + } + + // use intval instead of octdec to get proper cutting behavior with malformed numbers + $attributes['kind'] = LNumber::KIND_OCT; + return new LNumber(intval($str, 8), $attributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php new file mode 100644 index 0000000..a50d68f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php @@ -0,0 +1,28 @@ + '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ); + + /** + * Constructs a string scalar node. + * + * @param string $value Value of the string + * @param array $attributes Additional attributes + */ + public function __construct($value, array $attributes = array()) { + parent::__construct($attributes); + $this->value = $value; + } + + public function getSubNodeNames() { + return array('value'); + } + + /** + * @internal + * + * Parses a string token. + * + * @param string $str String token content + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string The parsed string + */ + public static function parse($str, $parseUnicodeEscape = true) { + $bLength = 0; + if ('b' === $str[0] || 'B' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + array('\\\\', '\\\''), + array( '\\', '\''), + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences( + substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape + ); + } + } + + /** + * @internal + * + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param null|string $quote Quote type + * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes + * + * @return string String with escape sequences parsed + */ + public static function parseEscapeSequences($str, $quote, $parseUnicodeEscape = true) { + if (null !== $quote) { + $str = str_replace('\\' . $quote, $quote, $str); + } + + $extra = ''; + if ($parseUnicodeEscape) { + $extra = '|u\{([0-9a-fA-F]+)\}'; + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', + function($matches) { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return chr(hexdec($str)); + } elseif ('u' === $str[0]) { + return self::codePointToUtf8(hexdec($matches[2])); + } else { + return chr(octdec($str)); + } + }, + $str + ); + } + + private static function codePointToUtf8($num) { + if ($num <= 0x7F) { + return chr($num); + } + if ($num <= 0x7FF) { + return chr(($num>>6) + 0xC0) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0xFFFF) { + return chr(($num>>12) + 0xE0) . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + if ($num <= 0x1FFFFF) { + return chr(($num>>18) + 0xF0) . chr((($num>>12)&0x3F) + 0x80) + . chr((($num>>6)&0x3F) + 0x80) . chr(($num&0x3F) + 0x80); + } + throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large'); + } + + /** + * @internal + * + * Parses a constant doc string. + * + * @param string $startToken Doc string start token content (<<num = $num; + } + + public function getSubNodeNames() { + return array('num'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php new file mode 100644 index 0000000..03f892c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php @@ -0,0 +1,30 @@ +cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('cond', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php new file mode 100644 index 0000000..58337ad --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php @@ -0,0 +1,34 @@ +types = $types; + $this->var = $var; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('types', 'var', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php new file mode 100644 index 0000000..0d41094 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php @@ -0,0 +1,47 @@ +flags = $flags; + $this->consts = $consts; + } + + public function getSubNodeNames() { + return array('flags', 'consts'); + } + + public function isPublic() { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + public function isProtected() { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + public function isPrivate() { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + public function isStatic() { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php new file mode 100644 index 0000000..f905335 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php @@ -0,0 +1,44 @@ +stmts as $stmt) { + if ($stmt instanceof ClassMethod) { + $methods[] = $stmt; + } + } + return $methods; + } + + /** + * Gets method with the given name defined directly in this class/interface/trait. + * + * @param string $name Name of the method (compared case-insensitively) + * + * @return ClassMethod|null Method node or null if the method does not exist + */ + public function getMethod($name) { + $lowerName = strtolower($name); + foreach ($this->stmts as $stmt) { + if ($stmt instanceof ClassMethod && $lowerName === strtolower($stmt->name)) { + return $stmt; + } + } + return null; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php new file mode 100644 index 0000000..de05390 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php @@ -0,0 +1,94 @@ + MODIFIER_PUBLIC: Flags + * 'byRef' => false : Whether to return by reference + * 'params' => array() : Parameters + * 'returnType' => null : Return type + * 'stmts' => array() : Statements + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->flags = isset($subNodes['flags']) ? $subNodes['flags'] + : (isset($subNodes['type']) ? $subNodes['type'] : 0); + $this->type = $this->flags; + $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; + $this->name = $name; + $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); + $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; + $this->stmts = array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('flags', 'byRef', 'name', 'params', 'returnType', 'stmts'); + } + + public function returnsByRef() { + return $this->byRef; + } + + public function getParams() { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getStmts() { + return $this->stmts; + } + + public function isPublic() { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + public function isProtected() { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + public function isPrivate() { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + public function isAbstract() { + return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT); + } + + public function isFinal() { + return (bool) ($this->flags & Class_::MODIFIER_FINAL); + } + + public function isStatic() { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php new file mode 100644 index 0000000..0a65e37 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php @@ -0,0 +1,99 @@ + true, + 'parent' => true, + 'static' => true, + ); + + /** + * Constructs a class node. + * + * @param string|null $name Name + * @param array $subNodes Array of the following optional subnodes: + * 'flags' => 0 : Flags + * 'extends' => null : Name of extended class + * 'implements' => array(): Names of implemented interfaces + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->flags = isset($subNodes['flags']) ? $subNodes['flags'] + : (isset($subNodes['type']) ? $subNodes['type'] : 0); + $this->type = $this->flags; + $this->name = $name; + $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : null; + $this->implements = isset($subNodes['implements']) ? $subNodes['implements'] : array(); + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('flags', 'name', 'extends', 'implements', 'stmts'); + } + + public function isAbstract() { + return (bool) ($this->flags & self::MODIFIER_ABSTRACT); + } + + public function isFinal() { + return (bool) ($this->flags & self::MODIFIER_FINAL); + } + + public function isAnonymous() { + return null === $this->name; + } + + /** + * @internal + */ + public static function verifyModifier($a, $b) { + if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) { + throw new Error('Multiple access type modifiers are not allowed'); + } + + if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) { + throw new Error('Multiple abstract modifiers are not allowed'); + } + + if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) { + throw new Error('Multiple static modifiers are not allowed'); + } + + if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) { + throw new Error('Multiple final modifiers are not allowed'); + } + + if ($a & 48 && $b & 48) { + throw new Error('Cannot use the final modifier on an abstract class member'); + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php new file mode 100644 index 0000000..8b2eecd --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php @@ -0,0 +1,26 @@ +consts = $consts; + } + + public function getSubNodeNames() { + return array('consts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php new file mode 100644 index 0000000..f78e19a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php @@ -0,0 +1,26 @@ +num = $num; + } + + public function getSubNodeNames() { + return array('num'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php new file mode 100644 index 0000000..829dbaf --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php @@ -0,0 +1,30 @@ +value pair node. + * + * @param string $key Key + * @param Node\Expr $value Value + * @param array $attributes Additional attributes + */ + public function __construct($key, Node\Expr $value, array $attributes = array()) { + parent::__construct($attributes); + $this->key = $key; + $this->value = $value; + } + + public function getSubNodeNames() { + return array('key', 'value'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php new file mode 100644 index 0000000..32739f3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php @@ -0,0 +1,30 @@ +declares = $declares; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('declares', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php new file mode 100644 index 0000000..dd4c6c8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php @@ -0,0 +1,30 @@ +cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('cond', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php new file mode 100644 index 0000000..11e1070 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php @@ -0,0 +1,26 @@ +exprs = $exprs; + } + + public function getSubNodeNames() { + return array('exprs'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php new file mode 100644 index 0000000..608878f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php @@ -0,0 +1,30 @@ +cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('cond', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php new file mode 100644 index 0000000..c91a148 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php @@ -0,0 +1,26 @@ +stmts = $stmts; + } + + public function getSubNodeNames() { + return array('stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php new file mode 100644 index 0000000..0e3eabb --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php @@ -0,0 +1,26 @@ +stmts = $stmts; + } + + public function getSubNodeNames() { + return array('stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php new file mode 100644 index 0000000..2ca88a3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php @@ -0,0 +1,39 @@ + array(): Init expressions + * 'cond' => array(): Loop conditions + * 'loop' => array(): Loop expressions + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->init = isset($subNodes['init']) ? $subNodes['init'] : array(); + $this->cond = isset($subNodes['cond']) ? $subNodes['cond'] : array(); + $this->loop = isset($subNodes['loop']) ? $subNodes['loop'] : array(); + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('init', 'cond', 'loop', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php new file mode 100644 index 0000000..d2c6432 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php @@ -0,0 +1,43 @@ + null : Variable to assign key to + * 'byRef' => false : Whether to assign value by reference + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->expr = $expr; + $this->keyVar = isset($subNodes['keyVar']) ? $subNodes['keyVar'] : null; + $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; + $this->valueVar = $valueVar; + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('expr', 'keyVar', 'byRef', 'valueVar', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php new file mode 100644 index 0000000..4c1f48d --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php @@ -0,0 +1,60 @@ + false : Whether to return by reference + * 'params' => array(): Parameters + * 'returnType' => null : Return type + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->byRef = isset($subNodes['byRef']) ? $subNodes['byRef'] : false; + $this->name = $name; + $this->params = isset($subNodes['params']) ? $subNodes['params'] : array(); + $this->returnType = isset($subNodes['returnType']) ? $subNodes['returnType'] : null; + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('byRef', 'name', 'params', 'returnType', 'stmts'); + } + + public function returnsByRef() { + return $this->byRef; + } + + public function getParams() { + return $this->params; + } + + public function getReturnType() { + return $this->returnType; + } + + public function getStmts() { + return $this->stmts; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php new file mode 100644 index 0000000..29fbc48 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php @@ -0,0 +1,26 @@ +vars = $vars; + } + + public function getSubNodeNames() { + return array('vars'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php new file mode 100644 index 0000000..b087fe0 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php @@ -0,0 +1,26 @@ +name = $name; + } + + public function getSubNodeNames() { + return array('name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php new file mode 100644 index 0000000..30837dd --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php @@ -0,0 +1,35 @@ +type = $type; + $this->prefix = $prefix; + $this->uses = $uses; + } + + public function getSubNodeNames() { + return array('type', 'prefix', 'uses'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php new file mode 100644 index 0000000..c33ec9f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php @@ -0,0 +1,26 @@ +remaining = $remaining; + } + + public function getSubNodeNames() { + return array('remaining'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php new file mode 100644 index 0000000..98bda35 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php @@ -0,0 +1,39 @@ + array(): Statements + * 'elseifs' => array(): Elseif clauses + * 'else' => null : Else clause + * @param array $attributes Additional attributes + */ + public function __construct(Node\Expr $cond, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->cond = $cond; + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + $this->elseifs = isset($subNodes['elseifs']) ? $subNodes['elseifs'] : array(); + $this->else = isset($subNodes['else']) ? $subNodes['else'] : null; + } + + public function getSubNodeNames() { + return array('cond', 'stmts', 'elseifs', 'else'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php new file mode 100644 index 0000000..accebe6 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php @@ -0,0 +1,26 @@ +value = $value; + } + + public function getSubNodeNames() { + return array('value'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php new file mode 100644 index 0000000..efb5891 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php @@ -0,0 +1,31 @@ + array(): Name of extended interfaces + * 'stmts' => array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->name = $name; + $this->extends = isset($subNodes['extends']) ? $subNodes['extends'] : array(); + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('name', 'extends', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php new file mode 100644 index 0000000..edd0ee9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php @@ -0,0 +1,26 @@ +name = $name; + } + + public function getSubNodeNames() { + return array('name'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php new file mode 100644 index 0000000..444855c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php @@ -0,0 +1,34 @@ +name = $name; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('name', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php new file mode 100644 index 0000000..270dd09 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php @@ -0,0 +1,13 @@ +flags = $flags; + $this->type = $flags; + $this->props = $props; + } + + public function getSubNodeNames() { + return array('flags', 'props'); + } + + public function isPublic() { + return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 + || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0; + } + + public function isProtected() { + return (bool) ($this->flags & Class_::MODIFIER_PROTECTED); + } + + public function isPrivate() { + return (bool) ($this->flags & Class_::MODIFIER_PRIVATE); + } + + public function isStatic() { + return (bool) ($this->flags & Class_::MODIFIER_STATIC); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php new file mode 100644 index 0000000..b2d29dc --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php @@ -0,0 +1,30 @@ +name = $name; + $this->default = $default; + } + + public function getSubNodeNames() { + return array('name', 'default'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php new file mode 100644 index 0000000..b642841 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php new file mode 100644 index 0000000..4bc5dd2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php @@ -0,0 +1,30 @@ +name = $name; + $this->default = $default; + } + + public function getSubNodeNames() { + return array('name', 'default'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php new file mode 100644 index 0000000..37cc0b3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php @@ -0,0 +1,26 @@ +vars = $vars; + } + + public function getSubNodeNames() { + return array('vars'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php new file mode 100644 index 0000000..72d667b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php @@ -0,0 +1,30 @@ +cond = $cond; + $this->cases = $cases; + } + + public function getSubNodeNames() { + return array('cond', 'cases'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php new file mode 100644 index 0000000..f8ff6aa --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Throw_.php @@ -0,0 +1,26 @@ +expr = $expr; + } + + public function getSubNodeNames() { + return array('expr'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php new file mode 100644 index 0000000..a29874b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php @@ -0,0 +1,31 @@ +traits = $traits; + $this->adaptations = $adaptations; + } + + public function getSubNodeNames() { + return array('traits', 'adaptations'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php new file mode 100644 index 0000000..c6038c8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php @@ -0,0 +1,13 @@ +trait = $trait; + $this->method = $method; + $this->newModifier = $newModifier; + $this->newName = $newName; + } + + public function getSubNodeNames() { + return array('trait', 'method', 'newModifier', 'newName'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php new file mode 100644 index 0000000..1f6bc1f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php @@ -0,0 +1,30 @@ +trait = $trait; + $this->method = $method; + $this->insteadof = $insteadof; + } + + public function getSubNodeNames() { + return array('trait', 'method', 'insteadof'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php new file mode 100644 index 0000000..eed5844 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php @@ -0,0 +1,26 @@ + array(): Statements + * @param array $attributes Additional attributes + */ + public function __construct($name, array $subNodes = array(), array $attributes = array()) { + parent::__construct($attributes); + $this->name = $name; + $this->stmts = isset($subNodes['stmts']) ? $subNodes['stmts'] : array(); + } + + public function getSubNodeNames() { + return array('name', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php new file mode 100644 index 0000000..0ff36cc --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php @@ -0,0 +1,34 @@ +stmts = $stmts; + $this->catches = $catches; + $this->finally = $finally; + } + + public function getSubNodeNames() { + return array('stmts', 'catches', 'finally'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php new file mode 100644 index 0000000..0f00fe9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php @@ -0,0 +1,26 @@ +vars = $vars; + } + + public function getSubNodeNames() { + return array('vars'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php new file mode 100644 index 0000000..2de8432 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php @@ -0,0 +1,38 @@ +getLast(); + } + + parent::__construct($attributes); + $this->type = $type; + $this->name = $name; + $this->alias = $alias; + } + + public function getSubNodeNames() { + return array('type', 'name', 'alias'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php new file mode 100644 index 0000000..6c89ebb --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php @@ -0,0 +1,43 @@ +type = $type; + $this->uses = $uses; + } + + public function getSubNodeNames() { + return array('type', 'uses'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php new file mode 100644 index 0000000..afad1b2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php @@ -0,0 +1,30 @@ +cond = $cond; + $this->stmts = $stmts; + } + + public function getSubNodeNames() { + return array('cond', 'stmts'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php new file mode 100644 index 0000000..1b757c7 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php @@ -0,0 +1,120 @@ +attributes = $attributes; + } + + /** + * Gets the type of the node. + * + * @return string Type of the node + */ + public function getType() { + $className = rtrim(get_class($this), '_'); + return strtr( + substr($className, strlen(Node::class) + 1), + '\\', + '_' + ); + } + + /** + * Gets line the node started in. + * + * @return int Line + */ + public function getLine() { + return $this->getAttribute('startLine', -1); + } + + /** + * Sets line the node started in. + * + * @param int $line Line + * + * @deprecated + */ + public function setLine($line) { + $this->setAttribute('startLine', (int) $line); + } + + /** + * Gets the doc comment of the node. + * + * The doc comment has to be the last comment associated with the node. + * + * @return null|Comment\Doc Doc comment object or null + */ + public function getDocComment() { + $comments = $this->getAttribute('comments'); + if (!$comments) { + return null; + } + + $lastComment = $comments[count($comments) - 1]; + if (!$lastComment instanceof Comment\Doc) { + return null; + } + + return $lastComment; + } + + /** + * Sets the doc comment of the node. + * + * This will either replace an existing doc comment or add it to the comments array. + * + * @param Comment\Doc $docComment Doc comment to set + */ + public function setDocComment(Comment\Doc $docComment) { + $comments = $this->getAttribute('comments', []); + + $numComments = count($comments); + if ($numComments > 0 && $comments[$numComments - 1] instanceof Comment\Doc) { + // Replace existing doc comment + $comments[$numComments - 1] = $docComment; + } else { + // Append new comment + $comments[] = $docComment; + } + + $this->setAttribute('comments', $comments); + } + + public function setAttribute($key, $value) { + $this->attributes[$key] = $value; + } + + public function hasAttribute($key) { + return array_key_exists($key, $this->attributes); + } + + public function &getAttribute($key, $default = null) { + if (!array_key_exists($key, $this->attributes)) { + return $default; + } else { + return $this->attributes[$key]; + } + } + + public function getAttributes() { + return $this->attributes; + } + + public function jsonSerialize() { + return ['nodeType' => $this->getType()] + get_object_vars($this); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php new file mode 100644 index 0000000..9946eb8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php @@ -0,0 +1,196 @@ +dumpComments = !empty($options['dumpComments']); + $this->dumpPositions = !empty($options['dumpPositions']); + } + + /** + * Dumps a node or array. + * + * @param array|Node $node Node or array to dump + * @param string|null $code Code corresponding to dumped AST. This only needs to be passed if + * the dumpPositions option is enabled and the dumping of node offsets + * is desired. + * + * @return string Dumped value + */ + public function dump($node, $code = null) { + $this->code = $code; + return $this->dumpRecursive($node); + } + + protected function dumpRecursive($node) { + if ($node instanceof Node) { + $r = $node->getType(); + if ($this->dumpPositions && null !== $p = $this->dumpPosition($node)) { + $r .= $p; + } + $r .= '('; + + foreach ($node->getSubNodeNames() as $key) { + $r .= "\n " . $key . ': '; + + $value = $node->$key; + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + if ('flags' === $key || 'newModifier' === $key) { + $r .= $this->dumpFlags($value); + } else if ('type' === $key && $node instanceof Include_) { + $r .= $this->dumpIncludeType($value); + } else if ('type' === $key + && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) { + $r .= $this->dumpUseType($value); + } else { + $r .= $value; + } + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + + if ($this->dumpComments && $comments = $node->getAttribute('comments')) { + $r .= "\n comments: " . str_replace("\n", "\n ", $this->dumpRecursive($comments)); + } + } elseif (is_array($node)) { + $r = 'array('; + + foreach ($node as $key => $value) { + $r .= "\n " . $key . ': '; + + if (null === $value) { + $r .= 'null'; + } elseif (false === $value) { + $r .= 'false'; + } elseif (true === $value) { + $r .= 'true'; + } elseif (is_scalar($value)) { + $r .= $value; + } else { + $r .= str_replace("\n", "\n ", $this->dumpRecursive($value)); + } + } + } elseif ($node instanceof Comment) { + return $node->getReformattedText(); + } else { + throw new \InvalidArgumentException('Can only dump nodes and arrays.'); + } + + return $r . "\n)"; + } + + protected function dumpFlags($flags) { + $strs = []; + if ($flags & Class_::MODIFIER_PUBLIC) { + $strs[] = 'MODIFIER_PUBLIC'; + } + if ($flags & Class_::MODIFIER_PROTECTED) { + $strs[] = 'MODIFIER_PROTECTED'; + } + if ($flags & Class_::MODIFIER_PRIVATE) { + $strs[] = 'MODIFIER_PRIVATE'; + } + if ($flags & Class_::MODIFIER_ABSTRACT) { + $strs[] = 'MODIFIER_ABSTRACT'; + } + if ($flags & Class_::MODIFIER_STATIC) { + $strs[] = 'MODIFIER_STATIC'; + } + if ($flags & Class_::MODIFIER_FINAL) { + $strs[] = 'MODIFIER_FINAL'; + } + + if ($strs) { + return implode(' | ', $strs) . ' (' . $flags . ')'; + } else { + return $flags; + } + } + + protected function dumpIncludeType($type) { + $map = [ + Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', + Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', + Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', + Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQURE_ONCE', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + protected function dumpUseType($type) { + $map = [ + Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', + Use_::TYPE_NORMAL => 'TYPE_NORMAL', + Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', + Use_::TYPE_CONSTANT => 'TYPE_CONSTANT', + ]; + + if (!isset($map[$type])) { + return $type; + } + return $map[$type] . ' (' . $type . ')'; + } + + protected function dumpPosition(Node $node) { + if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) { + return null; + } + + $start = $node->getAttribute('startLine'); + $end = $node->getAttribute('endLine'); + if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') + && null !== $this->code + ) { + $start .= ':' . $this->toColumn($this->code, $node->getAttribute('startFilePos')); + $end .= ':' . $this->toColumn($this->code, $node->getAttribute('endFilePos')); + } + return "[$start - $end]"; + } + + // Copied from Error class + private function toColumn($code, $pos) { + if ($pos > strlen($code)) { + throw new \RuntimeException('Invalid position information'); + } + + $lineStartPos = strrpos($code, "\n", $pos - strlen($code)); + if (false === $lineStartPos) { + $lineStartPos = -1; + } + + return $pos - $lineStartPos; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php new file mode 100644 index 0000000..cce43d9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php @@ -0,0 +1,204 @@ +visitors = array(); + } + + /** + * Adds a visitor. + * + * @param NodeVisitor $visitor Visitor to add + */ + public function addVisitor(NodeVisitor $visitor) { + $this->visitors[] = $visitor; + } + + /** + * Removes an added visitor. + * + * @param NodeVisitor $visitor + */ + public function removeVisitor(NodeVisitor $visitor) { + foreach ($this->visitors as $index => $storedVisitor) { + if ($storedVisitor === $visitor) { + unset($this->visitors[$index]); + break; + } + } + } + + /** + * Traverses an array of nodes using the registered visitors. + * + * @param Node[] $nodes Array of nodes + * + * @return Node[] Traversed array of nodes + */ + public function traverse(array $nodes) { + $this->stopTraversal = false; + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->beforeTraverse($nodes)) { + $nodes = $return; + } + } + + $nodes = $this->traverseArray($nodes); + + foreach ($this->visitors as $visitor) { + if (null !== $return = $visitor->afterTraverse($nodes)) { + $nodes = $return; + } + } + + return $nodes; + } + + protected function traverseNode(Node $node) { + foreach ($node->getSubNodeNames() as $name) { + $subNode =& $node->$name; + + if (is_array($subNode)) { + $subNode = $this->traverseArray($subNode); + if ($this->stopTraversal) { + break; + } + } elseif ($subNode instanceof Node) { + $traverseChildren = true; + foreach ($this->visitors as $visitor) { + $return = $visitor->enterNode($subNode); + if (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } else if (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else if (null !== $return) { + $subNode = $return; + } + } + + if ($traverseChildren) { + $subNode = $this->traverseNode($subNode); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitor) { + $return = $visitor->leaveNode($subNode); + if (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else if (null !== $return) { + if (is_array($return)) { + throw new \LogicException( + 'leaveNode() may only return an array ' . + 'if the parent structure is an array' + ); + } + $subNode = $return; + } + } + } + } + + return $node; + } + + protected function traverseArray(array $nodes) { + $doNodes = array(); + + foreach ($nodes as $i => &$node) { + if (is_array($node)) { + $node = $this->traverseArray($node); + if ($this->stopTraversal) { + break; + } + } elseif ($node instanceof Node) { + $traverseChildren = true; + foreach ($this->visitors as $visitor) { + $return = $visitor->enterNode($node); + if (self::DONT_TRAVERSE_CHILDREN === $return) { + $traverseChildren = false; + } else if (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } else if (null !== $return) { + $node = $return; + } + } + + if ($traverseChildren) { + $node = $this->traverseNode($node); + if ($this->stopTraversal) { + break; + } + } + + foreach ($this->visitors as $visitor) { + $return = $visitor->leaveNode($node); + + if (self::REMOVE_NODE === $return) { + $doNodes[] = array($i, array()); + break; + } else if (self::STOP_TRAVERSAL === $return) { + $this->stopTraversal = true; + break 2; + } elseif (is_array($return)) { + $doNodes[] = array($i, $return); + break; + } elseif (null !== $return) { + $node = $return; + } + } + } + } + + if (!empty($doNodes)) { + while (list($i, $replace) = array_pop($doNodes)) { + array_splice($nodes, $i, 1, $replace); + } + } + + return $nodes; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php new file mode 100644 index 0000000..0f88e46 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php @@ -0,0 +1,30 @@ + $node stays as-is + * * NodeTraverser::DONT_TRAVERSE_CHILDREN + * => Children of $node are not traversed. $node stays as-is + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|int|Node Node + */ + public function enterNode(Node $node); + + /** + * Called when leaving a node. + * + * Return value semantics: + * * null + * => $node stays as-is + * * NodeTraverser::REMOVE_NODE + * => $node is removed from the parent array + * * NodeTraverser::STOP_TRAVERSAL + * => Traversal is aborted. $node stays as-is + * * array (of Nodes) + * => The return value is merged into the parent array (at the position of the $node) + * * otherwise + * => $node is set to the return value + * + * @param Node $node Node + * + * @return null|false|int|Node|Node[] Node + */ + public function leaveNode(Node $node); + + /** + * Called once after traversal. + * + * Return value semantics: + * * null: $nodes stays as-is + * * otherwise: $nodes is set to the return value + * + * @param Node[] $nodes Array of nodes + * + * @return null|Node[] Array of nodes + */ + public function afterTraverse(array $nodes); +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php new file mode 100644 index 0000000..d56812b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php @@ -0,0 +1,272 @@ + [aliasName => originalName]] */ + protected $aliases; + + /** @var ErrorHandler Error handler */ + protected $errorHandler; + + /** @var bool Whether to preserve original names */ + protected $preserveOriginalNames; + + /** + * Constructs a name resolution visitor. + * + * Options: If "preserveOriginalNames" is enabled, an "originalName" attribute will be added to + * all name nodes that underwent resolution. + * + * @param ErrorHandler|null $errorHandler Error handler + * @param array $options Options + */ + public function __construct(ErrorHandler $errorHandler = null, array $options = []) { + $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; + $this->preserveOriginalNames = !empty($options['preserveOriginalNames']); + } + + public function beforeTraverse(array $nodes) { + $this->resetState(); + } + + public function enterNode(Node $node) { + if ($node instanceof Stmt\Namespace_) { + $this->resetState($node->name); + } elseif ($node instanceof Stmt\Use_) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, null); + } + } elseif ($node instanceof Stmt\GroupUse) { + foreach ($node->uses as $use) { + $this->addAlias($use, $node->type, $node->prefix); + } + } elseif ($node instanceof Stmt\Class_) { + if (null !== $node->extends) { + $node->extends = $this->resolveClassName($node->extends); + } + + foreach ($node->implements as &$interface) { + $interface = $this->resolveClassName($interface); + } + + if (null !== $node->name) { + $this->addNamespacedName($node); + } + } elseif ($node instanceof Stmt\Interface_) { + foreach ($node->extends as &$interface) { + $interface = $this->resolveClassName($interface); + } + + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Trait_) { + $this->addNamespacedName($node); + } elseif ($node instanceof Stmt\Function_) { + $this->addNamespacedName($node); + $this->resolveSignature($node); + } elseif ($node instanceof Stmt\ClassMethod + || $node instanceof Expr\Closure + ) { + $this->resolveSignature($node); + } elseif ($node instanceof Stmt\Const_) { + foreach ($node->consts as $const) { + $this->addNamespacedName($const); + } + } elseif ($node instanceof Expr\StaticCall + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\ClassConstFetch + || $node instanceof Expr\New_ + || $node instanceof Expr\Instanceof_ + ) { + if ($node->class instanceof Name) { + $node->class = $this->resolveClassName($node->class); + } + } elseif ($node instanceof Stmt\Catch_) { + foreach ($node->types as &$type) { + $type = $this->resolveClassName($type); + } + } elseif ($node instanceof Expr\FuncCall) { + if ($node->name instanceof Name) { + $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_FUNCTION); + } + } elseif ($node instanceof Expr\ConstFetch) { + $node->name = $this->resolveOtherName($node->name, Stmt\Use_::TYPE_CONSTANT); + } elseif ($node instanceof Stmt\TraitUse) { + foreach ($node->traits as &$trait) { + $trait = $this->resolveClassName($trait); + } + + foreach ($node->adaptations as $adaptation) { + if (null !== $adaptation->trait) { + $adaptation->trait = $this->resolveClassName($adaptation->trait); + } + + if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) { + foreach ($adaptation->insteadof as &$insteadof) { + $insteadof = $this->resolveClassName($insteadof); + } + } + } + } + } + + protected function resetState(Name $namespace = null) { + $this->namespace = $namespace; + $this->aliases = array( + Stmt\Use_::TYPE_NORMAL => array(), + Stmt\Use_::TYPE_FUNCTION => array(), + Stmt\Use_::TYPE_CONSTANT => array(), + ); + } + + protected function addAlias(Stmt\UseUse $use, $type, Name $prefix = null) { + // Add prefix for group uses + $name = $prefix ? Name::concat($prefix, $use->name) : $use->name; + // Type is determined either by individual element or whole use declaration + $type |= $use->type; + + // Constant names are case sensitive, everything else case insensitive + if ($type === Stmt\Use_::TYPE_CONSTANT) { + $aliasName = $use->alias; + } else { + $aliasName = strtolower($use->alias); + } + + if (isset($this->aliases[$type][$aliasName])) { + $typeStringMap = array( + Stmt\Use_::TYPE_NORMAL => '', + Stmt\Use_::TYPE_FUNCTION => 'function ', + Stmt\Use_::TYPE_CONSTANT => 'const ', + ); + + $this->errorHandler->handleError(new Error( + sprintf( + 'Cannot use %s%s as %s because the name is already in use', + $typeStringMap[$type], $name, $use->alias + ), + $use->getAttributes() + )); + return; + } + + $this->aliases[$type][$aliasName] = $name; + } + + /** @param Stmt\Function_|Stmt\ClassMethod|Expr\Closure $node */ + private function resolveSignature($node) { + foreach ($node->params as $param) { + $param->type = $this->resolveType($param->type); + } + $node->returnType = $this->resolveType($node->returnType); + } + + private function resolveType($node) { + if ($node instanceof Node\NullableType) { + $node->type = $this->resolveType($node->type); + return $node; + } + if ($node instanceof Name) { + return $this->resolveClassName($node); + } + return $node; + } + + protected function resolveClassName(Name $name) { + if ($this->preserveOriginalNames) { + // Save the original name + $originalName = $name; + $name = clone $originalName; + $name->setAttribute('originalName', $originalName); + } + + // don't resolve special class names + if (in_array(strtolower($name->toString()), array('self', 'parent', 'static'))) { + if (!$name->isUnqualified()) { + $this->errorHandler->handleError(new Error( + sprintf("'\\%s' is an invalid class name", $name->toString()), + $name->getAttributes() + )); + } + return $name; + } + + // fully qualified names are already resolved + if ($name->isFullyQualified()) { + return $name; + } + + $aliasName = strtolower($name->getFirst()); + if (!$name->isRelative() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { + // resolve aliases (for non-relative names) + $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]; + return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); + } + + // if no alias exists prepend current namespace + return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + } + + protected function resolveOtherName(Name $name, $type) { + if ($this->preserveOriginalNames) { + // Save the original name + $originalName = $name; + $name = clone $originalName; + $name->setAttribute('originalName', $originalName); + } + + // fully qualified names are already resolved + if ($name->isFullyQualified()) { + return $name; + } + + // resolve aliases for qualified names + $aliasName = strtolower($name->getFirst()); + if ($name->isQualified() && isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName])) { + $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$aliasName]; + return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes()); + } + + if ($name->isUnqualified()) { + if ($type === Stmt\Use_::TYPE_CONSTANT) { + // constant aliases are case-sensitive, function aliases case-insensitive + $aliasName = $name->getFirst(); + } + + if (isset($this->aliases[$type][$aliasName])) { + // resolve unqualified aliases + return new FullyQualified($this->aliases[$type][$aliasName], $name->getAttributes()); + } + + if (null === $this->namespace) { + // outside of a namespace unaliased unqualified is same as fully qualified + return new FullyQualified($name, $name->getAttributes()); + } + + // unqualified names inside a namespace cannot be resolved at compile-time + // add the namespaced version of the name as an attribute + $name->setAttribute('namespacedName', + FullyQualified::concat($this->namespace, $name, $name->getAttributes())); + return $name; + } + + // if no alias exists prepend current namespace + return FullyQualified::concat($this->namespace, $name, $name->getAttributes()); + } + + protected function addNamespacedName(Node $node) { + $node->namespacedName = Name::concat($this->namespace, $node->name); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php new file mode 100644 index 0000000..3e1743a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php @@ -0,0 +1,14 @@ +parsers = $parsers; + } + + public function parse($code, ErrorHandler $errorHandler = null) { + if (null === $errorHandler) { + $errorHandler = new ErrorHandler\Throwing; + } + + list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code); + if ($firstError === null) { + return $firstStmts; + } + + for ($i = 1, $c = count($this->parsers); $i < $c; ++$i) { + list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code); + if ($error === null) { + return $stmts; + } + } + + throw $firstError; + } + + private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code) { + $stmts = null; + $error = null; + try { + $stmts = $parser->parse($code, $errorHandler); + } catch (Error $error) {} + return [$stmts, $error]; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php new file mode 100644 index 0000000..4fbddaa --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php5.php @@ -0,0 +1,3153 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_THROW", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "';'", + "'{'", + "'}'", + "'('", + "')'", + "'$'", + "'`'", + "']'", + "'\"'" + ); + + protected $tokenToSymbol = array( + 0, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 53, 156, 157, 153, 52, 35, 157, + 151, 152, 50, 47, 7, 48, 49, 51, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 29, 148, + 41, 15, 43, 28, 65, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 67, 157, 155, 34, 157, 154, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 149, 33, 150, 55, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 1, 2, 3, 4, + 5, 6, 8, 9, 10, 11, 12, 13, 14, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 30, 31, 32, 36, 37, 38, 39, 40, 42, + 44, 45, 46, 54, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 66, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 157, 157, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 157, 157, 157, 157, + 157, 157, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147 + ); + + protected $action = array( + 674, 675, 676, 677, 678,-32766, 679, 680, 681, 717, + 718, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 0, 227, 228, 229, 230, 231, 232, 233, 234, 235, + 236, 237, 238,-32766,-32766,-32766,-32766,-32766,-32766,-32766, + -32766,-32767,-32767,-32767,-32767, 442, 239, 240,-32766,-32766, + -32766,-32766, 682,-32766, 308,-32766,-32766,-32766,-32766,-32766, + -32766,-32767,-32767,-32767,-32767,-32767, 683, 684, 685, 686, + 687, 688, 689, 1174, 462, 749,-32766,-32766,-32766,-32766, + -32766, 25, 690, 691, 692, 693, 694, 695, 696, 697, + 698, 699, 700, 720, 721, 722, 723, 724, 712, 713, + 714, 715, 716, 701, 702, 703, 704, 705, 706, 707, + 743, 744, 745, 746, 747, 748, 708, 709, 710, 711, + 741, 732, 730, 731, 727, 728, 520, 719, 725, 726, + 733, 734, 736, 735, 737, 738, 54, 55, 422, 56, + 57, 729, 740, 739, 421, 58, 59, 341, 60,-32766, + -32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 9,-32767, + -32767,-32767,-32767, 52, 327,-32766, 331, 947, 948, 949, + 946, 945, 944, 939, 1215, 29, 1217, 1216, 765, 766, + 823, 61, 62, 1101, -269, 1180, 764, 63, 1174, 64, + 293, 294, 65, 66, 67, 68, 69, 70, 71, 72, + 129, 26, 301, 73, 415,-32766,-32766,-32766,-32766, 1089, + 1090, 751, 635, 1180,-32766, 920, 206, 466,-32766,-32766, + -32766, 824, 409,-32766, 313,-32766, 902,-32766,-32766,-32766, + -32766,-32766,-32766, 215, 216, 217, 430,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32766, 122, 493, 947, 948, 949, + 946, 945, 944, 202, 475, 476, 284, 625, 127, 336, + 895, 896, 341, 479, 480, 1187, 1095, 1096, 1097, 1098, + 1092, 1093, 309, 494, 10, 443, 427, 494, 1099, 1094, + 427, 587, -220, 1212, 123, 41, 449, 336, 323, 1056, + 324, 423, -122, -122, -122, -4, 824, 465, 101, 102, + 103, 813, 303, 282, 40, 21, 424, -122, 467, -122, + 468, -122, 469, -122, 104, 425, 215, 216, 217, 30, + 31, 470, 426, 626, 32, 471, 427, 814, 74, 871, + 925, 351, 352, 472, 473, 358, 202, 243, 1101, 474, + 414, 1184, 795, 842, 477, 478, 300, 236, 237, 238, + 35, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 239, 240, 1038, 423, 350, 826, 640, + -122, 824, 465, 215, 216, 217, 813, 1140, 241, 40, + 21, 424, 48, 467, 440, 468, 334, 469, 297, 1038, + 425, 977, 979, 202, 30, 31, 470, 426, 416, 32, + 471, 1188, 1038, 74, 322, 1038, 351, 352, 472, 473, + -32766,-32766,-32766, 128, 474, 921, 811, 757, 842, 477, + 478,-32767,-32767,-32767,-32767, 96, 97, 98, 99, 100, + -32766, 20,-32766,-32766,-32766,-32766, 895, 896, 335, 1038, + 479, 423, -216, 826, 640, -4, 824, 465, 872, 494, + 1207, 813, 427, 1206, 40, 21, 424, 299, 467, 121, + 468, 1038, 469, -497, 118, 425, -201, -201, -201, 30, + 31, 470, 426, 297, 32, 471, 810, 911, 74, 216, + 217, 351, 352, 472, 473,-32766,-32766,-32766, 36, 474, + 51, 340, 795, 842, 477, 478, 207, 751, 202, 1180, + 126,-32766,-32766,-32766, 441,-32766, 417,-32766,-32766,-32766, + 49, 33, 296,-32766,-32766,-32766, 423, 208, 826, 640, + -201,-32766, 465,-32766,-32766, 807, 813, 379, 117, 40, + 21, 424, 1066, 467,-32766, 468, 217, 469, 805, 245, + 425, -200, -200, -200, 30, 31, 470, 426, 1038, 32, + 471, 286, 548, 74, 202, 824, 351, 352, 472, 473, + -32766,-32766,-32766, 494, 474, 125, 427, 795, 842, 477, + 478, 431, 120, 336, 1038, 803, 78, 79, 80, 494, + -32766, 436, 427, 646, 642, 126,-32766,-32766,-32766, 244, + 901, 246, 119, 826, 640, -200, 34, 298, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 209, 303, 202, 824, 423, 822, 1038, 215, 216, + 217, 465, 131, 130, 104, 813, 578, 1038, 40, 21, + 424, 650, 467, 835, 468, 647, 469, 315, 202, 425, + 285, 104, 643, 30, 31, 470, 824,-32766, 32, 471, + 295, 303, 74,-32766,-32766, 351, 352, 215, 216, 217, + -32766,-32766, 50, 474, 98, 99, 100, 233, 234, 235, + 239, 240, 456, 593, 644, 451, 22, 202, 132, 359, + 765, 766, 601, 602, 423, 758, 645, 924, 668, 301, + 465, 47, 858, 640, 813, 936, 656, 40, 21, 424, + 43, 467, 46, 468, 45, 469, 44, 53, 425, 751, + 607, 514, 30, 31, 470, 824, 423, 32, 471, 778, + 752, 74, 465, 437, 351, 352, 813, 535, 519, 40, + 21, 424, 474, 467, 536, 468, 1210, 469, 515, 435, + 425, 439, 518, 648, 30, 31, 470, 824, 624, 32, + 471, 614, 604, 74, 1059, 581, 351, 352,-32766, 526, + 634, 826, 640, 611, 474, 1139, 460, 434, 281, 621, + 328, 844, 314, 539, 14, 653, -80, 597, 837, 584, + 330, 843, 325, -398, 395, 423, 1146, 0, 0, 0, + 0, 465, 1100, 826, 640, 813, 598, 0, 40, 21, + 424, 0, 467, 0, 468, 0, 469, 0, 372, 425, + 0, 326, 0, 30, 31, 470, 824, 423, 32, 471, + 312, -498, 74, 465, -497, 351, 352, 813, 479, 0, + 40, 21, 424, 474, 467, 374, 468, 5, 469, 6, + 11, 425, -407, 13, -406, 30, 31, 470, 1036, 386, + 32, 471, 411, 410, 74, 387, 528, 351, 352, 436, + 856, 1213, 826, 640, 866, 474, 865, 874, 815, 800, + 821, 809, 763, 661, 660, 39, 38, 854, 931, 932, + 929, 859, 930, 820, 808, 761, 423, 928, 806, 804, + 798, 812, 465, 762, 826, 640, 813, 649, 77, 40, + 21, 424, 651, 467, 652, 468, 242, 469, 654, 655, + 425, 658, 663, 664, 30, 31, 470, 665, 124, 32, + 471, 332, 333, 74, 210, 211, 351, 352, 407, 641, + 212, 408, 213, 768, 474, 767, 864, 455, 1211, 1181, + 1179, 1165, 1177, 1080, 204, 913, 1185, 1175, 838, 210, + 211, 1040, 1089, 1090, 1041, 212,-32766, 213, 829, 863, + 1091, 1052, 759, 826, 640, 306, 839, 840, 760, 204, + 1214, 796, 662, 841, 770, 769, 937, 1089, 1090, 831, + 1042,-32766, 305, 304, 24, 1091, 27, 292, 291, 283, + 307, 338, 413, 419, 28, 205, 37, 42, 76, 75, + -32766, 0, 1018, 1017, 1082, 571, -216, 567, 1105, 1095, + 1096, 1097, 1098, 1092, 1093, 385, 903, 1046, 1043, 631, + 561, 1099, 1094, 463, 459, 457, 452, 380, 214, 0, + -32766, 18, 567, -217, 1095, 1096, 1097, 1098, 1092, 1093, + 385, 17, 16, 605, 0, -416, 1099, 1094, 1160, 1159, + 1106, 1209, 1079, 214, 1176,-32766, 1047, 0, 1164, 1178, + 1065, 1050, 1051, 1048, 1049, 0, 1145 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 8, 8, 9, 10, 11, + 12, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 0, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 8, 9, 10, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 7, 66, 67, 31, 32, + 33, 34, 54, 28, 7, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 68, 69, 70, 71, + 72, 73, 74, 79, 7, 77, 31, 32, 33, 34, + 35, 7, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 82, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 2, 3, 4, 5, + 6, 143, 144, 145, 7, 11, 12, 153, 14, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 103, 41, + 42, 43, 44, 67, 109, 79, 7, 112, 113, 114, + 115, 116, 117, 118, 77, 7, 79, 80, 102, 103, + 1, 47, 48, 139, 79, 79, 148, 53, 79, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 67, 67, 68, 69, 70, 8, 9, 10, 103, 75, + 76, 77, 77, 79, 109, 148, 7, 83, 8, 9, + 10, 1, 146, 118, 128, 28, 152, 30, 31, 32, + 33, 34, 35, 8, 9, 10, 102, 151, 28, 153, + 30, 31, 32, 33, 34, 149, 112, 112, 113, 114, + 115, 116, 117, 28, 120, 121, 7, 77, 149, 153, + 130, 131, 153, 129, 130, 1, 132, 133, 134, 135, + 136, 137, 138, 143, 7, 7, 146, 143, 144, 145, + 146, 82, 152, 150, 7, 151, 7, 153, 154, 152, + 156, 71, 72, 73, 74, 0, 1, 77, 50, 51, + 52, 81, 54, 13, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 66, 95, 8, 9, 10, 99, + 100, 101, 102, 143, 104, 105, 146, 148, 108, 29, + 150, 111, 112, 113, 114, 7, 28, 29, 139, 119, + 7, 77, 122, 123, 124, 125, 35, 50, 51, 52, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 66, 67, 12, 71, 7, 148, 149, + 150, 1, 77, 8, 9, 10, 81, 152, 13, 84, + 85, 86, 67, 88, 29, 90, 7, 92, 35, 12, + 95, 56, 57, 28, 99, 100, 101, 102, 103, 104, + 105, 152, 12, 108, 109, 12, 111, 112, 113, 114, + 8, 9, 10, 149, 119, 148, 148, 122, 123, 124, + 125, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 28, 152, 30, 31, 32, 33, 130, 131, 143, 12, + 129, 71, 152, 148, 149, 150, 1, 77, 148, 143, + 79, 81, 146, 82, 84, 85, 86, 7, 88, 13, + 90, 12, 92, 128, 149, 95, 96, 97, 98, 99, + 100, 101, 102, 35, 104, 105, 148, 79, 108, 9, + 10, 111, 112, 113, 114, 8, 9, 10, 13, 119, + 67, 67, 122, 123, 124, 125, 15, 77, 28, 79, + 147, 8, 9, 10, 149, 28, 123, 30, 31, 32, + 67, 140, 141, 8, 9, 10, 71, 15, 148, 149, + 150, 28, 77, 30, 31, 148, 81, 78, 15, 84, + 85, 86, 112, 88, 151, 90, 10, 92, 148, 15, + 95, 96, 97, 98, 99, 100, 101, 102, 12, 104, + 105, 153, 128, 108, 28, 1, 111, 112, 113, 114, + 8, 9, 10, 143, 119, 29, 146, 122, 123, 124, + 125, 151, 149, 153, 12, 148, 8, 9, 10, 143, + 28, 146, 146, 29, 149, 147, 31, 32, 33, 15, + 152, 15, 149, 148, 149, 150, 28, 35, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 15, 54, 28, 1, 71, 29, 12, 8, 9, + 10, 77, 149, 29, 66, 81, 153, 12, 84, 85, + 86, 29, 88, 35, 90, 29, 92, 29, 28, 95, + 35, 66, 29, 99, 100, 101, 1, 31, 104, 105, + 35, 54, 108, 31, 32, 111, 112, 8, 9, 10, + 8, 9, 67, 119, 47, 48, 49, 47, 48, 49, + 66, 67, 72, 73, 29, 72, 73, 28, 97, 98, + 102, 103, 106, 107, 71, 148, 149, 148, 149, 68, + 77, 67, 148, 149, 81, 148, 149, 84, 85, 86, + 67, 88, 67, 90, 67, 92, 67, 67, 95, 77, + 74, 77, 99, 100, 101, 1, 71, 104, 105, 77, + 77, 108, 77, 77, 111, 112, 81, 77, 77, 84, + 85, 86, 119, 88, 77, 90, 77, 92, 77, 77, + 95, 86, 79, 29, 99, 100, 101, 1, 79, 104, + 105, 79, 79, 108, 79, 87, 111, 112, 82, 82, + 89, 148, 149, 93, 119, 155, 102, 102, 94, 91, + 110, 123, 128, 94, 94, 29, 94, 96, 147, 96, + 126, 123, 126, 142, 146, 71, 139, -1, -1, -1, + -1, 77, 139, 148, 149, 81, 109, -1, 84, 85, + 86, -1, 88, -1, 90, -1, 92, -1, 142, 95, + -1, 127, -1, 99, 100, 101, 1, 71, 104, 105, + 128, 128, 108, 77, 128, 111, 112, 81, 129, -1, + 84, 85, 86, 119, 88, 146, 90, 142, 92, 142, + 142, 95, 142, 142, 142, 99, 100, 101, 154, 146, + 104, 105, 146, 146, 108, 146, 146, 111, 112, 146, + 148, 150, 148, 149, 148, 119, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, + 148, 148, 148, 148, 148, 148, 71, 148, 148, 148, + 148, 148, 77, 148, 148, 149, 81, 149, 149, 84, + 85, 86, 149, 88, 149, 90, 29, 92, 149, 149, + 95, 149, 149, 149, 99, 100, 101, 149, 149, 104, + 105, 149, 149, 108, 47, 48, 111, 112, 149, 149, + 53, 149, 55, 150, 119, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 67, 150, 150, 150, 150, 47, + 48, 150, 75, 76, 150, 53, 79, 55, 150, 150, + 83, 150, 150, 148, 149, 151, 150, 150, 150, 67, + 150, 150, 150, 150, 150, 150, 150, 75, 76, 150, + 152, 79, 151, 151, 151, 83, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, -1, 152, 152, 152, 152, 152, 130, 152, 132, + 133, 134, 135, 136, 137, 138, 152, 152, 152, 152, + 152, 144, 145, 152, 152, 152, 152, 152, 151, -1, + 153, 152, 130, 152, 132, 133, 134, 135, 136, 137, + 138, 152, 152, 155, -1, 154, 144, 145, 155, 155, + 155, 155, 155, 151, 155, 153, 155, -1, 155, 155, + 155, 155, 155, 155, 155, -1, 156 + ); + + protected $actionBase = array( + 0, 220, 295, 370, 445, 109, 109, 180, 744, -2, + -2, -2, -2, -2, 135, 655, 724, 756, 724, 623, + 554, 825, 825, 825, 438, 353, 625, 625, 862, 625, + 427, 390, 377, 449, 536, 615, 562, 393, 393, 393, + 393, 134, 134, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, + 393, 393, 393, 300, 179, 446, 475, 751, 750, 746, + 745, 838, 684, 860, 798, 799, 604, 800, 801, 802, + 803, 805, 797, 806, 898, 807, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, -3, 365, 225, + 308, 620, 662, 659, 659, 659, 659, 659, 659, 659, + 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, + 505, 505, 505, 505, 505, 505, 505, 470, 552, 552, + 552, 526, 887, 595, 912, 912, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 912, 912, 912, + 912, 912, 912, 912, 912, 912, 912, 493, -20, -20, + 477, 626, 402, 632, 210, 555, 197, 25, 25, 25, + 25, 25, 17, 45, 5, 5, 5, 5, 335, 380, + 380, 380, 380, 118, 118, 118, 118, 833, 827, 826, + 821, 311, 311, 709, 709, 631, 779, 627, 627, 630, + 630, 420, 420, 420, 420, 420, 420, 420, 420, 420, + 420, 383, 105, 859, 130, 130, 130, 130, 306, 44, + 657, 920, 264, 264, 264, 306, 248, 248, 248, 297, + 297, 297, 76, 687, 371, 86, 86, 86, 86, 371, + 86, 86, 588, 588, 588, 435, 759, 686, 436, 443, + 97, 483, 693, 819, 691, 796, 549, 710, 96, 717, + 716, 398, 675, 613, 610, 586, 651, 355, 398, 300, + 557, 423, 607, 753, 667, 38, 747, 328, 268, 424, + 547, 315, -6, 279, 782, 755, 863, 861, 249, 133, + 703, 607, 607, 607, 74, 199, 783, 789, 315, 290, + 614, 614, 614, 614, 835, 792, 614, 614, 614, 614, + 834, 795, 267, 67, 793, 137, 749, 642, 642, 642, + 642, 642, 642, 608, 642, 853, 671, 843, 843, 660, + 683, 608, 856, 856, 856, 856, 608, 642, 843, 843, + 608, 631, 843, 168, 608, 666, 642, 664, 664, 856, + 736, 735, 671, 673, 694, 843, 843, 843, 694, 660, + 608, 856, 697, 641, 209, 843, 856, 618, 618, 697, + 608, 618, 683, 618, 20, 597, 643, 855, 858, 852, + 644, 790, 668, 658, 847, 846, 857, 661, 672, 848, + 845, 720, 734, 733, 656, 513, 649, 647, 645, 634, + 705, 605, 702, 675, 723, 585, 585, 585, 706, 707, + 706, 585, 585, 585, 585, 585, 585, 585, 585, 911, + 712, 676, 654, 665, 732, 481, 699, 689, 502, 772, + 663, 720, 720, 831, 876, 885, 901, 704, 653, 842, + 878, 706, 919, 738, 277, 606, 841, 832, 713, 652, + 719, 706, 824, 706, 773, 706, 875, 830, 669, 720, + 828, 585, 874, 918, 917, 916, 915, 914, 913, 903, + 909, 650, 907, 731, 678, 884, 47, 854, 651, 708, + 648, 730, 159, 906, 822, 706, 706, 774, 759, 706, + 778, 729, 737, 900, 728, 883, 905, 663, 882, 706, + 674, 904, 159, 616, 646, 891, 680, 726, 851, 682, + 866, 850, 758, 574, 524, 721, 612, 752, 899, 889, + 864, 743, 763, 765, 576, 688, 685, 679, 839, 769, + 849, 722, 808, 811, 877, 692, 723, 711, 670, 690, + 681, 770, 814, 881, 739, 740, 741, 818, 742, 836, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 134, 134, 134, 134, -2, -2, -2, -2, 0, 0, + 0, 0, 0, -2, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 0, 0, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, + 134, 134, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 568, -20, -20, -20, + -20, 568, -20, -20, -20, -20, -20, -20, -20, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, -20, 568, 568, 568, + -20, 420, -20, 420, 420, 420, 420, 420, 420, 420, + 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, + 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, + 420, 420, 420, 420, 420, 420, 420, 420, 420, 420, + 420, 420, 420, 420, 420, 420, 568, 0, 0, 568, + -20, 568, -20, 568, -20, 568, 568, 568, 568, 568, + 568, -20, -20, -20, -20, -20, -20, 0, 248, 248, + 248, 248, -20, -20, -20, -20, 55, 55, 55, 55, + 420, 420, 420, 420, 420, 420, 248, 248, 297, 297, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 420, 55, 420, 642, 642, 642, 642, 642, 371, 371, + 371, 106, 106, 106, 642, 0, 0, 0, 0, 0, + 0, 642, 371, 0, 420, 420, 420, 420, 0, 420, + 420, 642, 642, 642, 642, 106, 371, 642, 843, 0, + 106, 591, 591, 591, 591, 159, 315, 0, 642, 642, + 0, 673, 0, 0, 0, 843, 0, 0, 0, 0, + 0, 585, 277, 842, 0, 360, 0, 0, 0, 0, + 0, 0, 0, 653, 360, 450, 450, 0, 0, 650, + 585, 585, 585, 0, 0, 653, 653, 0, 0, 0, + 0, 0, 0, 379, 653, 0, 0, 0, 0, 379, + 333, 0, 0, 333, 0, 159 + ); + + protected $actionDefault = array( + 3,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 525, 525,32767, 481, + 32767,32767,32767,32767,32767,32767,32767, 287, 287, 287, + 32767,32767,32767, 513, 513, 513, 513, 513, 513, 513, + 513, 513, 513, 513,32767,32767,32767,32767,32767, 369, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 375, 530,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767, 350, 351, 353, 354, + 286, 514, 237, 376, 529, 285, 239, 314, 485,32767, + 32767,32767, 316, 116, 248, 193, 484, 119, 284, 224, + 368, 370, 315, 291, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 290, 441, 347, 346, + 345, 443,32767, 442, 478, 478, 481,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 312, 469, 468, + 313, 439, 317, 440, 319, 444, 318, 335, 336, 333, + 334, 337, 446, 445, 462, 463, 460, 461, 289, 338, + 339, 340, 341, 464, 465, 466, 467, 271, 271, 271, + 271,32767,32767, 524, 524,32767,32767, 326, 327, 453, + 454,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 272,32767, 228, 228, 228, 228, 228,32767, + 32767,32767,32767,32767,32767,32767, 321, 322, 320, 448, + 449, 447,32767, 415,32767,32767,32767,32767,32767, 417, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 486, + 32767,32767,32767,32767,32767,32767,32767, 499, 404,32767, + 32767,32767, 397, 212, 214, 161, 472,32767,32767,32767, + 32767, 504, 331,32767,32767,32767,32767,32767,32767, 539, + 32767, 499,32767,32767,32767,32767,32767,32767,32767,32767, + 344, 323, 324, 325,32767,32767,32767,32767, 503, 497, + 456, 457, 458, 459,32767,32767, 450, 451, 452, 455, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 165,32767, 412,32767, 418, 418,32767, + 32767, 165,32767,32767,32767,32767, 165,32767, 502, 501, + 165,32767, 398, 480, 165, 178,32767, 176, 176,32767, + 198, 198,32767,32767, 180, 473, 492,32767, 180,32767, + 165,32767, 386, 167, 480,32767,32767, 230, 230, 386, + 165, 230,32767, 230,32767, 82, 422,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 399,32767,32767,32767,32767, 365, 366, 475, 488, + 32767, 489,32767, 397,32767, 329, 330, 332, 309,32767, + 311, 355, 356, 357, 358, 359, 360, 361, 363,32767, + 402,32767, 405,32767,32767,32767, 84, 108, 247,32767, + 537, 84, 400,32767,32767, 294, 537,32767,32767,32767, + 32767, 532,32767,32767, 288,32767,32767,32767, 84,32767, + 84, 243,32767, 163,32767, 522,32767, 497,32767, 401, + 32767, 328,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 498,32767,32767,32767,32767, 219,32767, 435,32767, + 84,32767, 179,32767,32767, 292, 238,32767,32767, 531, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 164, + 32767,32767, 181,32767,32767, 497,32767,32767,32767,32767, + 32767,32767,32767,32767, 283,32767,32767,32767,32767,32767, + 497,32767,32767,32767, 223,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 82, 60,32767, 265,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 121, 121, 3, 121, 121, 3, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 206, 250, 209, + 198, 198, 158, 250, 250, 250, 121, 121, 257 + ); + + protected $goto = array( + 162, 162, 136, 136, 141, 136, 137, 138, 139, 144, + 146, 183, 164, 160, 160, 160, 160, 141, 141, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 156, 157, 158, 159, 180, 135, 181, 495, 496, 362, + 497, 501, 502, 503, 504, 505, 506, 507, 508, 964, + 140, 142, 143, 145, 167, 172, 182, 198, 247, 250, + 252, 254, 256, 257, 258, 259, 260, 261, 269, 270, + 271, 272, 287, 288, 316, 317, 318, 381, 382, 383, + 551, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 147, 148, 149, 163, 150, 165, + 151, 199, 166, 152, 153, 154, 200, 155, 133, 627, + 569, 786, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 569, 1102, 636, 1102, 1102, 1102, + 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, + 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, + 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, + 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, 1102, + 525, 817, 499, 499, 499, 499, 499, 499, 1171, 510, + 1171, 510, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 511, 552, 511, 582, 608, 524, 887, 887, + 1192, 1192, 755, 851, 851, 851, 851, 170, 846, 852, + 524, 524, 173, 174, 175, 390, 391, 392, 393, 169, + 197, 201, 203, 251, 253, 255, 262, 263, 264, 265, + 266, 267, 273, 274, 275, 276, 289, 290, 319, 320, + 321, 396, 397, 398, 399, 171, 176, 248, 249, 177, + 178, 179, 389, 610, 545, 545, 575, 541, 8, 343, + 1078, 1077, 543, 543, 498, 500, 531, 547, 576, 579, + 589, 595, 550, 756, 568, 574, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 568, 568, 568, 516, + 445, 447, 935, 638, 329, 311, 1103, 620, 933, 521, + 521, 521, 521, 779, 553, 554, 555, 556, 557, 558, + 559, 560, 562, 591, 857, 613, 540, 521, 619, 512, + 360, 512, 905, 432, 432, 432, 432, 432, 432, 546, + 779, 779, 1196, 432, 432, 432, 432, 432, 432, 432, + 432, 432, 432, 1067, 1163, 1067, 894, 894, 894, 894, + 894, 1170, 363, 1170, 585, 588, 633, 894, 371, 371, + 371, 1060, 1186, 1186, 1186, 3, 4, 1067, 1067, 1067, + 1067, 600, 1067, 1067, 521, 521, 538, 570, 521, 521, + 617, 521, 371, 1151, 962, 609, 1169, 388, 772, 772, + 780, 780, 780, 782, 522, 771, 1189, 1202, 1202, 537, + 377, 659, 564, 549, 596, 884, 615, 618, 880, 622, + 623, 630, 632, 637, 639, 900, 1202, 1203, 1203, 364, + 592, 346, 406, 529, 1205, 754, 891, 542, 278, 279, + 280, 1011, 349, 1063, 1064, 400, 1203, 1060, 873, 855, + 853, 855, 657, 453, 513, 882, 877, 1083, 344, 345, + 1061, 1162, 1061, 12, 1021, 19, 15, 357, 775, 773, + 1062, 370, 375, 909, 404, 666, 1053, 448, 1058, 783, + 580, 563, 861, 914, 1148, 461, 951, 0, 0, 0, + 0, 0, 0, 23, 0, 0, 0, 0, 606, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 943, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 530 + ); + + protected $gotoCheck = array( + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 53, + 63, 25, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 119, 5, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 94, 46, 110, 110, 110, 110, 110, 110, 111, 63, + 111, 63, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 40, 110, 36, 36, 40, 71, 71, + 71, 71, 11, 63, 63, 63, 63, 23, 63, 63, + 40, 40, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 47, 47, 47, 47, 47, 47, 91, 66, + 117, 117, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 2, 12, 53, 2, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 8, + 7, 7, 7, 7, 118, 118, 7, 7, 7, 8, + 8, 8, 8, 19, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 29, 57, 8, 8, 57, 115, + 57, 115, 78, 53, 53, 53, 53, 53, 53, 102, + 19, 19, 132, 53, 53, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 76, 53, 53, 53, 53, 53, + 53, 112, 43, 112, 56, 56, 56, 53, 116, 116, + 116, 76, 112, 112, 112, 26, 26, 53, 53, 53, + 53, 120, 53, 53, 8, 8, 8, 8, 8, 8, + 53, 8, 116, 124, 94, 45, 112, 116, 19, 19, + 19, 19, 19, 19, 8, 19, 130, 133, 133, 28, + 44, 28, 28, 8, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 75, 133, 134, 134, 54, + 64, 64, 64, 54, 133, 10, 73, 54, 61, 61, + 61, 95, 14, 76, 76, 18, 134, 76, 10, 10, + 10, 10, 10, 54, 10, 10, 10, 30, 66, 66, + 76, 76, 76, 54, 30, 30, 30, 30, 21, 20, + 76, 9, 13, 79, 17, 68, 106, 59, 108, 22, + 60, 30, 65, 80, 123, 101, 93, -1, -1, -1, + -1, -1, -1, 30, -1, -1, -1, -1, 30, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 91, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 94 + ); + + protected $gotoBase = array( + 0, 0, -340, 0, 0, 142, 0, 345, 27, 186, + 483, 230, 301, 173, 170, 0, 0, 116, 162, 41, + 169, 184, 87, 35, 0, 101, -241, 0, -182, 354, + 92, 0, 0, 0, 0, 0, 187, 0, 0, -24, + 199, 0, 0, 372, 168, 163, 183, 1, 0, 0, + 0, 0, 0, 102, 53, 0, 109, -83, 0, 89, + 82, -175, 0, -92, 154, 83, -152, 0, 166, 0, + 0, -53, 0, 178, 0, 160, 65, 0, 357, 165, + 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 274, 0, 74, 159, 188, 0, 0, 0, 0, + 0, 76, 362, 320, 0, 0, 108, 0, 107, 0, + -79, -93, 110, 0, 0, 78, 106, -23, 31, -47, + 226, 0, 0, 80, 237, 0, 0, 0, 0, 0, + 172, 0, 363, 147, 167, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 464, 670, 2, 671, 742, 750, 603, 481, 517, + 792, 793, 794, 366, 412, 482, 365, 401, 394, 781, + 774, 776, 784, 168, 402, 787, 1, 789, 523, 825, + 1012, 353, 797, 354, 594, 799, 533, 801, 802, 134, + 483, 367, 368, 534, 376, 583, 816, 268, 373, 818, + 355, 819, 828, 356, 616, 599, 565, 612, 484, 444, + 577, 277, 544, 1075, 572, 860, 342, 868, 667, 876, + 879, 485, 566, 890, 450, 898, 1088, 384, 904, 910, + 915, 918, 420, 403, 590, 922, 923, 7, 927, 628, + 629, 942, 302, 950, 963, 418, 1031, 1033, 486, 487, + 527, 458, 509, 532, 488, 1054, 438, 405, 1057, 489, + 490, 428, 429, 1072, 348, 1156, 347, 446, 310, 1143, + 586, 1107, 454, 1195, 1152, 339, 491, 492, 361, 378, + 1190, 433, 1197, 1204, 337, 369, 573 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 8, 8, 9, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 14, 14, 15, 15, + 15, 15, 17, 17, 13, 13, 18, 18, 19, 19, + 20, 20, 21, 21, 16, 16, 22, 24, 24, 25, + 26, 26, 28, 27, 27, 27, 27, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 10, 10, 50, 50, + 52, 51, 51, 44, 44, 54, 54, 55, 55, 11, + 12, 12, 12, 58, 58, 58, 59, 59, 62, 62, + 60, 60, 64, 64, 37, 37, 46, 46, 49, 49, + 49, 48, 48, 65, 38, 38, 38, 38, 66, 66, + 67, 67, 68, 68, 35, 35, 31, 31, 69, 33, + 33, 70, 32, 32, 34, 34, 45, 45, 45, 56, + 56, 72, 72, 73, 73, 75, 75, 75, 74, 74, + 57, 57, 76, 76, 76, 77, 77, 78, 78, 78, + 41, 41, 79, 79, 79, 42, 42, 80, 80, 61, + 61, 81, 81, 81, 81, 86, 86, 87, 87, 88, + 88, 88, 88, 88, 89, 90, 90, 85, 85, 82, + 82, 84, 84, 92, 92, 91, 91, 91, 91, 91, + 91, 83, 83, 93, 93, 43, 43, 36, 36, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, + 39, 39, 39, 30, 30, 40, 40, 98, 98, 99, + 99, 99, 99, 105, 94, 94, 101, 101, 107, 107, + 108, 109, 109, 109, 109, 109, 109, 63, 63, 53, + 53, 53, 95, 95, 113, 113, 110, 110, 114, 114, + 114, 114, 96, 96, 96, 100, 100, 100, 106, 106, + 119, 119, 119, 119, 119, 119, 119, 119, 119, 119, + 119, 119, 119, 23, 23, 23, 23, 23, 23, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 121, + 121, 121, 104, 104, 97, 97, 97, 97, 120, 120, + 123, 123, 122, 122, 124, 124, 47, 47, 47, 47, + 126, 126, 125, 125, 125, 125, 125, 127, 127, 112, + 112, 115, 115, 111, 111, 128, 128, 128, 128, 116, + 116, 116, 116, 103, 103, 117, 117, 117, 117, 71, + 129, 129, 130, 130, 130, 102, 102, 131, 131, 132, + 132, 132, 132, 118, 118, 118, 118, 134, 135, 133, + 133, 133, 133, 133, 133, 133, 136, 136, 136 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 1, 1, 3, + 5, 4, 3, 4, 2, 3, 1, 1, 7, 8, + 6, 7, 3, 1, 3, 1, 3, 1, 1, 3, + 1, 2, 1, 2, 3, 1, 3, 3, 1, 3, + 2, 0, 1, 1, 1, 1, 1, 3, 5, 8, + 3, 5, 9, 3, 2, 3, 2, 3, 2, 3, + 2, 3, 3, 3, 1, 2, 5, 7, 9, 5, + 6, 3, 3, 2, 2, 1, 1, 1, 0, 2, + 8, 0, 4, 1, 3, 0, 1, 0, 1, 10, + 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, + 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, + 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, + 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, + 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, + 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, + 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, + 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, + 0, 3, 3, 9, 3, 1, 3, 0, 2, 4, + 5, 4, 4, 4, 3, 1, 1, 1, 3, 1, + 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 3, 1, 3, 3, 1, 0, 1, 1, + 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, + 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, + 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 1, 3, 5, 4, 3, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 1, 1, 1, 3, 2, 1, + 2, 10, 11, 3, 3, 2, 4, 4, 3, 4, + 4, 4, 4, 7, 3, 2, 0, 4, 1, 3, + 2, 2, 4, 6, 2, 2, 4, 1, 1, 1, + 2, 3, 1, 1, 1, 1, 1, 1, 3, 3, + 4, 4, 0, 2, 1, 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 2, 1, 3, 1, 4, 3, 1, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, + 4, 3, 1, 3, 1, 1, 3, 3, 0, 2, + 0, 1, 3, 1, 3, 1, 1, 1, 1, 1, + 6, 4, 3, 4, 2, 4, 4, 1, 3, 1, + 2, 1, 1, 4, 1, 3, 6, 4, 4, 4, + 4, 1, 4, 0, 1, 1, 3, 1, 1, 4, + 3, 1, 1, 1, 0, 0, 2, 3, 1, 3, + 1, 4, 2, 2, 2, 1, 2, 1, 1, 1, + 4, 3, 3, 3, 6, 3, 1, 1, 1 + ); + + protected function reduceRule0() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule1() { + $this->semValue = $this->handleNamespaces($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule2() { + if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; + } + + protected function reduceRule3() { + $this->semValue = array(); + } + + protected function reduceRule4() { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule5() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule6() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule7() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule8() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule9() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule10() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule11() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule12() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule13() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule14() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule15() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule16() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule17() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule18() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule19() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule20() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule21() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule22() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule23() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule24() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule25() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule26() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule27() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule28() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule29() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule30() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule31() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule32() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule33() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule34() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule35() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule36() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule37() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule38() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule39() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule40() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule41() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule42() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule43() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule44() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule45() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule46() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule47() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule48() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule49() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule50() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule51() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule52() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule53() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule54() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule55() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule56() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule57() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule58() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule59() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule60() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule61() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule62() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule63() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule64() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule65() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule66() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule67() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule68() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule69() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule70() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule71() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule72() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule73() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule74() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule75() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule76() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule77() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule78() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule79() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule80() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule81() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule82() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule83() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule84() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule85() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule86() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule87() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule88() { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule89() { + $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule90() { + $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule91() { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule92() { + $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule93() { + $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule94() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule95() { + $this->semValue = new Stmt\Const_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule96() { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + } + + protected function reduceRule97() { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + } + + protected function reduceRule98() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule99() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); + } + + protected function reduceRule100() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule101() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule102() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule103() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule104() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule105() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule106() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule107() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule108() { + $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(1-1)); + } + + protected function reduceRule109() { + $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(3-3)); + } + + protected function reduceRule110() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule111() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule112() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + } + + protected function reduceRule113() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; $this->semValue->type = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule114() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule115() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule116() { + $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule117() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule118() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule119() { + $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule120() { + if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; + } + + protected function reduceRule121() { + $this->semValue = array(); + } + + protected function reduceRule122() { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule123() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule124() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule125() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule126() { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule127() { + + if ($this->semStack[$this->stackPos-(3-2)]) { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$this->stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + } + + protected function reduceRule128() { + $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(5-2)], ['stmts' => is_array($this->semStack[$this->stackPos-(5-3)]) ? $this->semStack[$this->stackPos-(5-3)] : array($this->semStack[$this->stackPos-(5-3)]), 'elseifs' => $this->semStack[$this->stackPos-(5-4)], 'else' => $this->semStack[$this->stackPos-(5-5)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule129() { + $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(8-2)], ['stmts' => $this->semStack[$this->stackPos-(8-4)], 'elseifs' => $this->semStack[$this->stackPos-(8-5)], 'else' => $this->semStack[$this->stackPos-(8-6)]], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); + } + + protected function reduceRule130() { + $this->semValue = new Stmt\While_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule131() { + $this->semValue = new Stmt\Do_($this->semStack[$this->stackPos-(5-4)], is_array($this->semStack[$this->stackPos-(5-2)]) ? $this->semStack[$this->stackPos-(5-2)] : array($this->semStack[$this->stackPos-(5-2)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule132() { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$this->stackPos-(9-3)], 'cond' => $this->semStack[$this->stackPos-(9-5)], 'loop' => $this->semStack[$this->stackPos-(9-7)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + } + + protected function reduceRule133() { + $this->semValue = new Stmt\Switch_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule134() { + $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule135() { + $this->semValue = new Stmt\Break_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule136() { + $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule137() { + $this->semValue = new Stmt\Continue_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule138() { + $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule139() { + $this->semValue = new Stmt\Return_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule140() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule141() { + $this->semValue = new Stmt\Global_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule142() { + $this->semValue = new Stmt\Static_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule143() { + $this->semValue = new Stmt\Echo_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule144() { + $this->semValue = new Stmt\InlineHTML($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule145() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule146() { + $this->semValue = new Stmt\Unset_($this->semStack[$this->stackPos-(5-3)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule147() { + $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(7-3)], $this->semStack[$this->stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$this->stackPos-(7-5)][1], 'stmts' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule148() { + $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(9-3)], $this->semStack[$this->stackPos-(9-7)][0], ['keyVar' => $this->semStack[$this->stackPos-(9-5)], 'byRef' => $this->semStack[$this->stackPos-(9-7)][1], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + } + + protected function reduceRule149() { + $this->semValue = new Stmt\Declare_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule150() { + $this->semValue = new Stmt\TryCatch($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-5)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + } + + protected function reduceRule151() { + $this->semValue = new Stmt\Throw_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule152() { + $this->semValue = new Stmt\Goto_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule153() { + $this->semValue = new Stmt\Label($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule154() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule155() { + $this->semValue = array(); /* means: no statement */ + } + + protected function reduceRule156() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule157() { + $startAttributes = $this->startAttributeStack[$this->stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + } + + protected function reduceRule158() { + $this->semValue = array(); + } + + protected function reduceRule159() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule160() { + $this->semValue = new Stmt\Catch_(array($this->semStack[$this->stackPos-(8-3)]), substr($this->semStack[$this->stackPos-(8-4)], 1), $this->semStack[$this->stackPos-(8-7)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); + } + + protected function reduceRule161() { + $this->semValue = null; + } + + protected function reduceRule162() { + $this->semValue = new Stmt\Finally_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule163() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule164() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule165() { + $this->semValue = false; + } + + protected function reduceRule166() { + $this->semValue = true; + } + + protected function reduceRule167() { + $this->semValue = false; + } + + protected function reduceRule168() { + $this->semValue = true; + } + + protected function reduceRule169() { + $this->semValue = new Stmt\Function_($this->semStack[$this->stackPos-(10-3)], ['byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-5)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); + } + + protected function reduceRule170() { + $this->semValue = new Stmt\Class_($this->semStack[$this->stackPos-(7-2)], ['type' => $this->semStack[$this->stackPos-(7-1)], 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $this->stackPos-(7-2)); + } + + protected function reduceRule171() { + $this->semValue = new Stmt\Interface_($this->semStack[$this->stackPos-(6-2)], ['extends' => $this->semStack[$this->stackPos-(6-3)], 'stmts' => $this->semStack[$this->stackPos-(6-5)]], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $this->stackPos-(6-2)); + } + + protected function reduceRule172() { + $this->semValue = new Stmt\Trait_($this->semStack[$this->stackPos-(5-2)], ['stmts' => $this->semStack[$this->stackPos-(5-4)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule173() { + $this->semValue = 0; + } + + protected function reduceRule174() { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + } + + protected function reduceRule175() { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + } + + protected function reduceRule176() { + $this->semValue = null; + } + + protected function reduceRule177() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule178() { + $this->semValue = array(); + } + + protected function reduceRule179() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule180() { + $this->semValue = array(); + } + + protected function reduceRule181() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule182() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule183() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule184() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule185() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule186() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule187() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule188() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule189() { + $this->semValue = null; + } + + protected function reduceRule190() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule191() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule192() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule193() { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule194() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule195() { + $this->semValue = $this->semStack[$this->stackPos-(4-3)]; + } + + protected function reduceRule196() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule197() { + $this->semValue = $this->semStack[$this->stackPos-(5-3)]; + } + + protected function reduceRule198() { + $this->semValue = array(); + } + + protected function reduceRule199() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule200() { + $this->semValue = new Stmt\Case_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule201() { + $this->semValue = new Stmt\Case_(null, $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule202() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule203() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule204() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule205() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule206() { + $this->semValue = array(); + } + + protected function reduceRule207() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule208() { + $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(3-2)], is_array($this->semStack[$this->stackPos-(3-3)]) ? $this->semStack[$this->stackPos-(3-3)] : array($this->semStack[$this->stackPos-(3-3)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule209() { + $this->semValue = array(); + } + + protected function reduceRule210() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule211() { + $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule212() { + $this->semValue = null; + } + + protected function reduceRule213() { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$this->stackPos-(2-2)]) ? $this->semStack[$this->stackPos-(2-2)] : array($this->semStack[$this->stackPos-(2-2)]), $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule214() { + $this->semValue = null; + } + + protected function reduceRule215() { + $this->semValue = new Stmt\Else_($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule216() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); + } + + protected function reduceRule217() { + $this->semValue = array($this->semStack[$this->stackPos-(2-2)], true); + } + + protected function reduceRule218() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); + } + + protected function reduceRule219() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule220() { + $this->semValue = array(); + } + + protected function reduceRule221() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule222() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule223() { + $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(4-4)], 1), null, $this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); + } + + protected function reduceRule224() { + $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(6-4)], 1), $this->semStack[$this->stackPos-(6-6)], $this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-3)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); + } + + protected function reduceRule225() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule226() { + $this->semValue = 'array'; + } + + protected function reduceRule227() { + $this->semValue = 'callable'; + } + + protected function reduceRule228() { + $this->semValue = null; + } + + protected function reduceRule229() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule230() { + $this->semValue = null; + } + + protected function reduceRule231() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule232() { + $this->semValue = array(); + } + + protected function reduceRule233() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule234() { + $this->semValue = array(new Node\Arg($this->semStack[$this->stackPos-(3-2)], false, false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes)); + } + + protected function reduceRule235() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule236() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule237() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(1-1)], false, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule238() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], true, false, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule239() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], false, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule240() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule241() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule242() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule243() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule244() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule245() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule246() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule247() { + $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule248() { + $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule249() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule250() { + $this->semValue = array(); + } + + protected function reduceRule251() { + $this->semValue = new Stmt\Property($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $this->stackPos-(3-1)); + } + + protected function reduceRule252() { + $this->semValue = new Stmt\ClassConst($this->semStack[$this->stackPos-(3-2)], 0, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule253() { + $this->semValue = new Stmt\ClassMethod($this->semStack[$this->stackPos-(9-4)], ['type' => $this->semStack[$this->stackPos-(9-1)], 'byRef' => $this->semStack[$this->stackPos-(9-3)], 'params' => $this->semStack[$this->stackPos-(9-6)], 'returnType' => $this->semStack[$this->stackPos-(9-8)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $this->stackPos-(9-1)); + } + + protected function reduceRule254() { + $this->semValue = new Stmt\TraitUse($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule255() { + $this->semValue = array(); + } + + protected function reduceRule256() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule257() { + $this->semValue = array(); + } + + protected function reduceRule258() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule259() { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule260() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(5-1)][0], $this->semStack[$this->stackPos-(5-1)][1], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule261() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], null, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule262() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule263() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule264() { + $this->semValue = array($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)]); + } + + protected function reduceRule265() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule266() { + $this->semValue = array(null, $this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule267() { + $this->semValue = null; + } + + protected function reduceRule268() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule269() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule270() { + $this->semValue = 0; + } + + protected function reduceRule271() { + $this->semValue = 0; + } + + protected function reduceRule272() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule273() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule274() { + $this->checkModifier($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->stackPos-(2-2)); $this->semValue = $this->semStack[$this->stackPos-(2-1)] | $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule275() { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + } + + protected function reduceRule276() { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + } + + protected function reduceRule277() { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + } + + protected function reduceRule278() { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + } + + protected function reduceRule279() { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + } + + protected function reduceRule280() { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + } + + protected function reduceRule281() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule282() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule283() { + $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule284() { + $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule285() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule286() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule287() { + $this->semValue = array(); + } + + protected function reduceRule288() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule289() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule290() { + $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule291() { + $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule292() { + $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule293() { + $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule294() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule295() { + $this->semValue = new Expr\Clone_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule296() { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule297() { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule298() { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule299() { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule300() { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule301() { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule302() { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule303() { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule304() { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule305() { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule306() { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule307() { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule308() { + $this->semValue = new Expr\PostInc($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule309() { + $this->semValue = new Expr\PreInc($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule310() { + $this->semValue = new Expr\PostDec($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule311() { + $this->semValue = new Expr\PreDec($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule312() { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule313() { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule314() { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule315() { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule316() { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule317() { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule318() { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule319() { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule320() { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule321() { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule322() { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule323() { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule324() { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule325() { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule326() { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule327() { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule328() { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule329() { + $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule330() { + $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule331() { + $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule332() { + $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule333() { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule334() { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule335() { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule336() { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule337() { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule338() { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule339() { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule340() { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule341() { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule342() { + $this->semValue = new Expr\Instanceof_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule343() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule344() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule345() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule346() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule347() { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule348() { + $this->semValue = new Expr\Isset_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule349() { + $this->semValue = new Expr\Empty_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule350() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule351() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule352() { + $this->semValue = new Expr\Eval_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule353() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule354() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule355() { + $this->semValue = new Expr\Cast\Int_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule356() { + $this->semValue = new Expr\Cast\Double($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule357() { + $this->semValue = new Expr\Cast\String_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule358() { + $this->semValue = new Expr\Cast\Array_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule359() { + $this->semValue = new Expr\Cast\Object_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule360() { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule361() { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule362() { + $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$this->stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$this->stackPos-(2-2)], $attrs); + } + + protected function reduceRule363() { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule364() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule365() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule366() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule367() { + $this->semValue = new Expr\ShellExec($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule368() { + $this->semValue = new Expr\Print_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule369() { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule370() { + $this->semValue = new Expr\YieldFrom($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule371() { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-4)], 'uses' => $this->semStack[$this->stackPos-(10-6)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); + } + + protected function reduceRule372() { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$this->stackPos-(11-3)], 'params' => $this->semStack[$this->stackPos-(11-5)], 'uses' => $this->semStack[$this->stackPos-(11-7)], 'returnType' => $this->semStack[$this->stackPos-(11-8)], 'stmts' => $this->semStack[$this->stackPos-(11-10)]], $this->startAttributeStack[$this->stackPos-(11-1)] + $this->endAttributes); + } + + protected function reduceRule373() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule374() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule375() { + $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule376() { + $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule377() { + $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $attrs); + } + + protected function reduceRule378() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule379() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule380() { + $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(4-1)][0] === "'" || ($this->semStack[$this->stackPos-(4-1)][1] === "'" && ($this->semStack[$this->stackPos-(4-1)][0] === 'b' || $this->semStack[$this->stackPos-(4-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); + $this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(4-1)]), $attrs), $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule381() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule382() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule383() { + $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-2)]); + $this->checkClass($this->semValue[0], -1); + } + + protected function reduceRule384() { + $this->semValue = new Expr\New_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule385() { + list($class, $ctorArgs) = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule386() { + $this->semValue = array(); + } + + protected function reduceRule387() { + $this->semValue = $this->semStack[$this->stackPos-(4-3)]; + } + + protected function reduceRule388() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule389() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule390() { + $this->semValue = new Expr\ClosureUse(substr($this->semStack[$this->stackPos-(2-2)], 1), $this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule391() { + $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule392() { + $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule393() { + $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-4)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule394() { + + if ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\StaticPropertyFetch) { + $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(2-1)]->class, new Expr\Variable($this->semStack[$this->stackPos-(2-1)]->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } elseif ($this->semStack[$this->stackPos-(2-1)] instanceof Node\Expr\ArrayDimFetch) { + $tmp = $this->semStack[$this->stackPos-(2-1)]; + while ($tmp->var instanceof Node\Expr\ArrayDimFetch) { + $tmp = $tmp->var; + } + + $this->semValue = new Expr\StaticCall($tmp->var->class, $this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + $tmp->var = new Expr\Variable($tmp->var->name, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } else { + throw new \Exception; + } + + } + + protected function reduceRule395() { + $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule396() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule397() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule398() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule399() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule400() { + $this->semValue = new Name\FullyQualified($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule401() { + $this->semValue = new Name\Relative($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule402() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule403() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule404() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule405() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule406() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule407() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule408() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule409() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule410() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule411() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule412() { + $this->semValue = null; + } + + protected function reduceRule413() { + $this->semValue = null; + } + + protected function reduceRule414() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule415() { + $this->semValue = array(); + } + + protected function reduceRule416() { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$this->stackPos-(1-1)], '`', false), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes)); + } + + protected function reduceRule417() { + foreach ($this->semStack[$this->stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', false); } }; $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule418() { + $this->semValue = array(); + } + + protected function reduceRule419() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule420() { + $this->semValue = $this->parseLNumber($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes, true); + } + + protected function reduceRule421() { + $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule422() { + $attrs = $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(1-1)][0] === "'" || ($this->semStack[$this->stackPos-(1-1)][1] === "'" && ($this->semStack[$this->stackPos-(1-1)][0] === 'b' || $this->semStack[$this->stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); + $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(1-1)], false), $attrs); + } + + protected function reduceRule423() { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule424() { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule425() { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule426() { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule427() { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule428() { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule429() { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule430() { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule431() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; + $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], false), $attrs); + } + + protected function reduceRule432() { + $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(2-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(2-1)], $matches); $attrs['docLabel'] = $matches[1];; + $this->semValue = new Scalar\String_('', $attrs); + } + + protected function reduceRule433() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule434() { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule435() { + $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule436() { + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule437() { + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule438() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule439() { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule440() { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule441() { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule442() { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule443() { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule444() { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule445() { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule446() { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule447() { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule448() { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule449() { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule450() { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule451() { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule452() { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule453() { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule454() { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule455() { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule456() { + $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule457() { + $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule458() { + $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule459() { + $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule460() { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule461() { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule462() { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule463() { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule464() { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule465() { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule466() { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule467() { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule468() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule469() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule470() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule471() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule472() { + $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule473() { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule474() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule475() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule476() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule477() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; + foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, true); } } $s->value = preg_replace('~(\r\n|\n|\r)\z~', '', $s->value); if ('' === $s->value) array_pop($this->semStack[$this->stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule478() { + $this->semValue = array(); + } + + protected function reduceRule479() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule480() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule481() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule482() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule483() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule484() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule485() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule486() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule487() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule488() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule489() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule490() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule491() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule492() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule493() { + $this->semValue = new Expr\MethodCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule494() { + $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule495() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule496() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule497() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule498() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule499() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule500() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule501() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule502() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule503() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule504() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule505() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], substr($this->semStack[$this->stackPos-(3-3)], 1), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule506() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-5)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule507() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule508() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule509() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule510() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule511() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule512() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule513() { + $this->semValue = null; + } + + protected function reduceRule514() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule515() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule516() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule517() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule518() { + $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + } + + protected function reduceRule519() { + $this->semValue = new Expr\List_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule520() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule521() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule522() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule523() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule524() { + $this->semValue = null; + } + + protected function reduceRule525() { + $this->semValue = array(); + } + + protected function reduceRule526() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule527() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule528() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule529() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule530() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule531() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-1)], true, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule532() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(2-2)], null, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule533() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule534() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule535() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule536() { + $this->semValue = array($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); + } + + protected function reduceRule537() { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule538() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule539() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule540() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule541() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule542() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule543() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule544() { + $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-4)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule545() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule546() { + $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule547() { + $this->semValue = $this->parseNumString($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule548() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php new file mode 100644 index 0000000..591bd61 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php @@ -0,0 +1,2872 @@ +'", + "T_IS_GREATER_OR_EQUAL", + "T_SL", + "T_SR", + "'+'", + "'-'", + "'.'", + "'*'", + "'/'", + "'%'", + "'!'", + "T_INSTANCEOF", + "'~'", + "T_INC", + "T_DEC", + "T_INT_CAST", + "T_DOUBLE_CAST", + "T_STRING_CAST", + "T_ARRAY_CAST", + "T_OBJECT_CAST", + "T_BOOL_CAST", + "T_UNSET_CAST", + "'@'", + "T_POW", + "'['", + "T_NEW", + "T_CLONE", + "T_EXIT", + "T_IF", + "T_ELSEIF", + "T_ELSE", + "T_ENDIF", + "T_LNUMBER", + "T_DNUMBER", + "T_STRING", + "T_STRING_VARNAME", + "T_VARIABLE", + "T_NUM_STRING", + "T_INLINE_HTML", + "T_ENCAPSED_AND_WHITESPACE", + "T_CONSTANT_ENCAPSED_STRING", + "T_ECHO", + "T_DO", + "T_WHILE", + "T_ENDWHILE", + "T_FOR", + "T_ENDFOR", + "T_FOREACH", + "T_ENDFOREACH", + "T_DECLARE", + "T_ENDDECLARE", + "T_AS", + "T_SWITCH", + "T_ENDSWITCH", + "T_CASE", + "T_DEFAULT", + "T_BREAK", + "T_CONTINUE", + "T_GOTO", + "T_FUNCTION", + "T_CONST", + "T_RETURN", + "T_TRY", + "T_CATCH", + "T_FINALLY", + "T_THROW", + "T_USE", + "T_INSTEADOF", + "T_GLOBAL", + "T_STATIC", + "T_ABSTRACT", + "T_FINAL", + "T_PRIVATE", + "T_PROTECTED", + "T_PUBLIC", + "T_VAR", + "T_UNSET", + "T_ISSET", + "T_EMPTY", + "T_HALT_COMPILER", + "T_CLASS", + "T_TRAIT", + "T_INTERFACE", + "T_EXTENDS", + "T_IMPLEMENTS", + "T_OBJECT_OPERATOR", + "T_LIST", + "T_ARRAY", + "T_CALLABLE", + "T_CLASS_C", + "T_TRAIT_C", + "T_METHOD_C", + "T_FUNC_C", + "T_LINE", + "T_FILE", + "T_START_HEREDOC", + "T_END_HEREDOC", + "T_DOLLAR_OPEN_CURLY_BRACES", + "T_CURLY_OPEN", + "T_PAAMAYIM_NEKUDOTAYIM", + "T_NAMESPACE", + "T_NS_C", + "T_DIR", + "T_NS_SEPARATOR", + "T_ELLIPSIS", + "';'", + "'{'", + "'}'", + "'('", + "')'", + "'`'", + "']'", + "'\"'", + "'$'" + ); + + protected $tokenToSymbol = array( + 0, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 53, 155, 157, 156, 52, 35, 157, + 151, 152, 50, 47, 7, 48, 49, 51, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 29, 148, + 41, 15, 43, 28, 65, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 67, 157, 154, 34, 157, 153, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 149, 33, 150, 55, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 1, 2, 3, 4, + 5, 6, 8, 9, 10, 11, 12, 13, 14, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 30, 31, 32, 36, 37, 38, 39, 40, 42, + 44, 45, 46, 54, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 66, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 80, 81, 157, 157, + 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 157, 157, 157, 157, + 157, 157, 138, 139, 140, 141, 142, 143, 144, 145, + 146, 147 + ); + + protected $action = array( + 583, 584, 585, 586, 587, 1037, 588, 589, 590, 626, + 627, 479, 29, 101, 102, 103, 104, 105, 106, 107, + 108, 109, 110, 111, 112,-32766,-32766,-32766, 97, 98, + 99, 0, 241, 387, -282,-32766,-32766,-32766,-32766, -487, + 1081, 544, 1084, 1082, 100,-32766, 664,-32766,-32766,-32766, + -32766,-32766, 591, 901, 903,-32766, 30,-32766,-32766,-32766, + -32766,-32766,-32766, 1034,-32766, 295, 592, 593, 594, 595, + 596, 597, 598,-32766, 274, 658, 869, 870, 871, 868, + 867, 866, 599, 600, 601, 602, 603, 604, 605, 606, + 607, 608, 609, 629, 630, 631, 632, 633, 621, 622, + 623, 624, 625, 610, 611, 612, 613, 614, 615, 616, + 652, 653, 654, 655, 656, 657, 617, 618, 619, 620, + 650, 641, 639, 640, 636, 637, -251, 628, 634, 635, + 642, 643, 645, 644, 646, 647, 74, 75, 76, 556, + 266, 638, 649, 648, 739, 44, 45, 392, 46, 47, + 375, 680, 681, 73, 48, 49, 28, 50, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 218, 241, 996, -487, -443, -487,-32766,-32766,-32766, + 51, 52, 116, 663, 100, 339, 53, 242, 54, 221, + 222, 55, 56, 57, 58, 59, 60, 61, 62, -173, + 24, 234, 63, 347, 393,-32766,-32766,-32766, 1001, 1002, + 394, 228, 1034, 217, 729,-32766, 1000, 34, 19, 395, + 1051, 396, 127, 397, 118, 398, -442, 24, 399, 984, + 43, 267, 36, 37, 400, 351, -443, 38, 401, 1034, + 248, 64, 289, 1000, 288, 290, 248,-32766, 741, 226, + -443, 1034, 404, 405, 406, 442, 291, -443, 371, -446, + 376, -251, 409, 410, 26, 1006, 1007, 1008, 1009, 1003, + 1004, 245, 977,-32766,-32766,-32766, 419, 1010, 1005, 349, + -488, 226, 549, 278, 65,-32766, 257, -442, 262, 266, + 410, 660, 467,-32766, 1073,-32766, 1048, 1072,-32766,-32766, + -32766, -442,-32766,-32766,-32766, 1078,-32766, 1034, -442,-32766, + -445, 67, 1014,-32766,-32766,-32766, 266,-32766,-32766,-32766, + -479, 123,-32766, 660, -172,-32766, 418,-32766, 266, 531, + -32766,-32766,-32766,-32766,-32766,-32766,-32766, 223,-32766, 560, + 977,-32766, 818, 819, -173,-32766,-32766,-32766, 818, 819, + -32766,-32766, -227, 561,-32766, 27, 224,-32766, 418,-32766, + -32766, 122, -441,-32766, -232,-32766, 824, 40, 124, 227, + -88, 791, 265,-32766, 984, 1052,-32766,-32766,-32766, 660, + 94, 95, 96,-32766, 266, 364,-32766,-32766,-32766, 42, + -32766, 553,-32766, 122,-32766,-32766,-32766,-32766,-32766,-32766, + -32766,-32766,-32766,-32766,-32766,-32766,-32766,-32766, 363, 532, + -32766, 660, 554,-32766, 418,-32766, -477, 9,-32766,-32766, + -32766,-32766,-32766, -441,-32766, -488,-32766, -488, 249,-32766, + 248, 660, 121,-32766,-32766,-32766,-32766, -441,-32766,-32766, + 359, 555,-32766, 551, -441,-32766, 418, 517, 518, 115, + 250,-32766, 1034,-32766,-32767,-32767,-32767,-32767, 92, 93, + 94, 95, 96, 23, 308, -479, 504, 20, 344, -172, + 225, 117, 741, 126,-32766, 533, -441, 564, 349,-32766, + 660, 133, 847,-32766,-32766, 977, 120,-32766,-32766,-32766, + 792,-32766, 119,-32766, 114,-32766, 345, 419,-32766, 113, + 349, 130,-32766,-32766,-32766, 132,-32766,-32766,-32766, 738, + 741,-32766, 660, 241,-32766, 418,-32766, 244,-32766,-32766, + -32766,-32766,-32766,-32766, 128,-32766, 753,-32766, 527, 266, + -32766, 741, 818, 819,-32766,-32766,-32766, -441, 100,-32766, + -32766, 129, 313,-32766, 680, 681,-32766, 418, 41,-32766, + 660, -441,-32766, 453,-32766, 660, 321,-32766, -441,-32766, + 777, -477,-32766,-32766,-32766, 1083,-32766, 261,-32766, 441, + -32766, 385, 8,-32766, 437, 24, 360,-32766,-32766,-32766, + 497, 498,-32766,-32766,-32766, 501,-32766, 1034,-32766,-32766, + 418, 1000, 818, 819, 660, 846, 575,-32766,-32766, 358, + -4,-32766,-32766,-32766, 301,-32766, 1076,-32766, 661,-32766, + 455, 696,-32766, 858, 565, 513,-32766,-32766,-32766, 440, + 977,-32766,-32766, 973, 446,-32766, 505,-32766,-32766, 418, + -133, -133, -133,-32766,-32766,-32766,-32766, 409, 410, 451, + 542, 528, 509, 521, 510, -133, 12, -133, -80, -133, + 216, -133, 495,-32766, 458,-32766,-32766,-32766,-32766, 67, + 348, 356, 259, 258, 266, 1016,-32766,-32766,-32766,-32766, + 260, 402, 403, 869, 870, 871, 868, 867, 866, 861, + 715, 760, 407, 408, 977, 761, 762,-32766, 11,-32766, + -32766,-32766,-32766,-32766,-32766,-32767,-32767,-32767,-32767,-32767, + 264, 229, 348, 337, 1013, 852, 741, 17, -133, 256, + -212, -212, -212, 402, 403, -400, 348, 5, 307, 775, + 758, 21, 672, 760, 407, 408, 329, 402, 403, -211, + -211, -211, 448, 24, 326, 348, 715, 760, 407, 408, + 341, 340, 318, 276, 325, 1034, 402, 403, 741, 1000, + -4,-32766,-32766,-32766, 359, 715, 760, 407, 408, 755, + 552, 33, 741, 573, -212, 574, 720, 842, 794, 778, + 32,-32766, 851,-32766,-32766, 854, 853, 850, 977, 773, + 785, 741, 718, -211, 786, 843, 741, 252, 334, 550, + 557, 558, 559, 562, 272, 409, 410, 273, 571, 570, + 568, 566, 563, 335, 0, 757, 965, 783, 859, 0, + 746, 964, 963, 756, 748, 683, 0, 67, 1079, 682, + 685, 784, 266, 567, 716, 1080, 675, 674, 684, 759, + 1049, 1046, 1041, 1077, 1035, 1028, 0, -444, -467, -446, + -445, 22, 25, 31, 35, 39, 66, 338, 336, 275, + 240, 239, 238, 237, 220, 219, 134, 131, 125, 72, + 71, 70, 69, 68, -469, 0, 310, 475, 941, 491, + 541, 944, 13, 969, 825, 998, 940, 988, -230, -88, + 538, 390, 383, 380, 377, 311, 18, 16, 15, 14, + -227, -228, 0, 957, -412, 0, 503, 0, 1040, 1075, + 1026, 1027, 997, 0, 1015 + ); + + protected $actionCheck = array( + 2, 3, 4, 5, 6, 1, 8, 9, 10, 11, + 12, 48, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 8, 9, 10, 50, 51, + 52, 0, 54, 7, 79, 8, 9, 10, 8, 7, + 77, 77, 79, 80, 66, 28, 1, 30, 31, 32, + 33, 34, 54, 56, 57, 28, 13, 30, 31, 32, + 33, 34, 35, 79, 109, 7, 68, 69, 70, 71, + 72, 73, 74, 118, 7, 77, 112, 113, 114, 115, + 116, 117, 84, 85, 86, 87, 88, 89, 90, 91, + 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 123, 124, 125, 126, 127, 7, 129, 130, 131, + 132, 133, 134, 135, 136, 137, 8, 9, 10, 29, + 156, 143, 144, 145, 1, 2, 3, 4, 5, 6, + 29, 102, 103, 149, 11, 12, 28, 14, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 13, 54, 1, 152, 67, 154, 8, 9, 10, + 47, 48, 13, 148, 66, 146, 53, 7, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 7, + 67, 68, 69, 70, 71, 8, 9, 10, 75, 76, + 77, 7, 79, 13, 81, 1, 83, 84, 85, 86, + 1, 88, 67, 90, 7, 92, 67, 67, 95, 1, + 7, 67, 99, 100, 101, 102, 128, 104, 105, 79, + 28, 108, 7, 83, 111, 112, 28, 1, 148, 35, + 142, 79, 119, 120, 121, 82, 7, 149, 7, 151, + 149, 152, 129, 130, 7, 132, 133, 134, 135, 136, + 137, 138, 112, 8, 9, 10, 143, 144, 145, 146, + 7, 35, 149, 33, 151, 71, 153, 128, 155, 156, + 130, 77, 128, 28, 79, 81, 77, 82, 84, 85, + 86, 142, 88, 1, 90, 150, 92, 79, 149, 95, + 151, 151, 139, 99, 100, 101, 156, 71, 104, 105, + 7, 149, 108, 77, 7, 111, 112, 81, 156, 79, + 84, 85, 86, 119, 88, 1, 90, 35, 92, 29, + 112, 95, 130, 131, 152, 99, 100, 101, 130, 131, + 104, 105, 152, 29, 108, 140, 141, 111, 112, 8, + 9, 147, 67, 149, 152, 119, 152, 67, 149, 35, + 152, 29, 7, 71, 1, 152, 8, 9, 10, 77, + 47, 48, 49, 81, 156, 7, 84, 85, 86, 67, + 88, 29, 90, 147, 92, 149, 28, 95, 30, 31, + 32, 99, 100, 101, 1, 71, 104, 105, 7, 77, + 108, 77, 29, 111, 112, 81, 7, 7, 84, 85, + 86, 119, 88, 128, 90, 152, 92, 154, 128, 95, + 28, 77, 29, 99, 100, 101, 1, 142, 104, 105, + 146, 29, 108, 149, 149, 111, 112, 72, 73, 149, + 128, 149, 79, 119, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 7, 142, 152, 72, 73, 7, 152, + 35, 149, 148, 15, 71, 143, 67, 29, 146, 1, + 77, 15, 150, 149, 81, 112, 15, 84, 85, 86, + 148, 88, 15, 90, 15, 92, 123, 143, 95, 15, + 146, 15, 99, 100, 101, 15, 71, 104, 105, 29, + 148, 108, 77, 54, 111, 112, 81, 29, 1, 84, + 85, 86, 119, 88, 29, 90, 35, 92, 74, 156, + 95, 148, 130, 131, 99, 100, 101, 128, 66, 104, + 105, 97, 98, 108, 102, 103, 111, 112, 67, 71, + 77, 142, 149, 77, 119, 77, 78, 82, 149, 81, + 148, 152, 84, 85, 86, 80, 88, 110, 90, 77, + 92, 102, 103, 95, 77, 67, 77, 99, 100, 101, + 106, 107, 104, 105, 149, 79, 108, 79, 71, 111, + 112, 83, 130, 131, 77, 148, 149, 119, 81, 77, + 0, 84, 85, 86, 77, 88, 77, 90, 77, 92, + 77, 77, 95, 148, 149, 79, 99, 100, 101, 79, + 112, 104, 105, 79, 82, 108, 87, 149, 111, 112, + 72, 73, 74, 8, 9, 10, 119, 129, 130, 86, + 89, 91, 93, 96, 96, 87, 94, 89, 94, 91, + 94, 93, 109, 28, 94, 30, 31, 32, 33, 151, + 102, 102, 127, 126, 156, 139, 149, 8, 9, 10, + 109, 113, 114, 112, 113, 114, 115, 116, 117, 118, + 122, 123, 124, 125, 112, 123, 123, 28, 142, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 126, 35, 102, 103, 139, 148, 148, 152, 150, 109, + 96, 97, 98, 113, 114, 142, 102, 142, 142, 148, + 150, 152, 122, 123, 124, 125, 146, 113, 114, 96, + 97, 98, 146, 67, 146, 102, 122, 123, 124, 125, + 146, 146, 146, 143, 146, 79, 113, 114, 148, 83, + 150, 8, 9, 10, 146, 122, 123, 124, 125, 147, + 149, 148, 148, 148, 150, 148, 148, 148, 148, 148, + 148, 28, 148, 30, 31, 148, 148, 148, 112, 148, + 148, 148, 148, 150, 148, 148, 148, 152, 149, 149, + 149, 149, 149, 149, 149, 129, 130, 149, 149, 149, + 149, 149, 149, 149, -1, 150, 150, 150, 150, -1, + 150, 150, 150, 150, 150, 150, -1, 151, 150, 150, + 150, 150, 156, 150, 150, 150, 150, 150, 150, 150, + 150, 150, 150, 150, 150, 150, -1, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 151, 151, -1, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, + 152, 152, -1, 153, 153, -1, 154, -1, 154, 154, + 154, 154, 154, -1, 155 + ); + + protected $actionBase = array( + 0, 568, 610, 624, 643, 182, 342, 567, -2, -2, + -2, -2, -36, 393, 110, 334, 110, 372, 422, 648, + 648, 648, 224, 256, 312, 312, 312, 488, 413, 445, + 344, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 527, 527, 527, 527, 527, + 527, 527, 527, 527, 527, 45, 45, 352, 43, 645, + 729, 725, 565, 730, 566, 724, 726, 168, 693, 694, + 505, 695, 692, 691, 690, 727, 752, 579, 728, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 30, 179, 361, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, + 207, 207, 207, 207, 207, 207, 207, 275, 275, 275, + 753, 378, 419, 635, 17, 305, 27, 669, 669, 669, + 669, 669, 423, 423, 423, 423, 676, 676, 518, 170, + 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, + 689, 580, 665, 666, 383, 343, 343, 222, 222, 222, + 222, 238, 228, -45, 412, 183, 536, 759, 472, 229, + 229, 118, 169, -22, -22, -22, 49, 552, 582, 582, + 582, 582, 225, 225, 582, 582, 4, -37, 305, 305, + 332, 305, 452, 452, 452, 364, 304, 485, 364, 621, + 558, 667, 557, 681, 310, 283, 32, 605, -16, 604, + 569, -16, 484, 404, 385, 737, 45, 583, 45, 45, + 45, 45, 45, 45, 45, 45, 45, -16, -16, 45, + 121, 45, 457, 352, 475, 469, 543, 174, 655, 327, + 233, 165, 469, 469, 469, 658, 649, 119, 210, 664, + 202, 479, 323, 260, 483, 483, 501, 507, 486, 483, + 483, 483, 483, 516, 483, 700, 700, 704, 501, 483, + 700, 501, 227, 411, 245, 259, 501, 388, 547, 483, + 584, 584, 261, 507, 550, 214, 466, 545, 700, 700, + 545, 486, 190, 501, 375, 625, 627, 553, 622, 67, + 498, 498, 471, 553, 26, 501, 498, 516, 420, 58, + 498, 31, 705, 722, 490, 721, 702, 720, 706, 719, + 537, 650, 572, 573, 714, 713, 718, 502, 532, 703, + 701, 596, 509, 494, 489, 585, 491, 696, 569, 618, + 482, 482, 482, 491, 698, 482, 482, 482, 482, 482, + 482, 482, 482, 758, 267, 586, 563, 487, 606, 570, + 481, 662, 575, 596, 596, 684, 751, 750, 541, 712, + 735, 717, 632, 468, 744, 711, 683, 608, 544, 598, + 710, 743, 734, 661, 494, 733, 685, 539, 596, 686, + 482, 697, 723, 756, 757, 699, 754, 742, 590, 495, + 755, 687, 732, 660, 659, 623, 747, 736, 741, 688, + 740, 628, 549, 749, 559, 707, 546, 708, 651, 680, + 679, 496, 629, 678, 716, 630, 746, 745, 748, 631, + 642, 652, 653, 500, 675, 476, 647, 715, 320, 464, + 560, 646, 554, 731, 674, 654, 709, 644, 581, 673, + 672, 738, 564, 618, 556, 467, 562, 561, 663, 671, + 739, 458, 641, 639, 638, 637, 670, 634, 668, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, + 143, 143, 143, -2, -2, -2, 0, 0, 0, 0, + -2, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + -3, 128, 128, -3, 128, 128, 128, 128, 128, 128, + -22, -22, -22, -22, 364, 364, 364, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 571, 571, + 571, 571, 364, -22, -22, 364, 364, 364, 364, 364, + 364, 571, 364, 225, 225, 225, 364, -16, -16, 0, + 0, 0, 0, 0, 483, 225, 364, 364, 364, 364, + 0, 0, 364, 364, -16, 0, 0, 0, 0, 0, + 483, 483, 483, 0, 483, 225, 0, 45, 454, 454, + 454, 454, 0, 0, 0, 483, 0, 483, 550, 0, + 0, 0, 0, 501, 0, 700, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 482, 712, 0, 541, 0, 0, 0, + 482, 482, 482, 541, 541, 0, 0, 541 + ); + + protected $actionDefault = array( + 3,32767,32767,32767,32767,32767,32767,32767,32767, 88, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767, 88, 489, 489, 489,32767,32767,32767, + 32767, 302, 302, 302,32767, 481, 439, 439, 439, 439, + 439, 439, 439, 481,32767,32767,32767,32767,32767, 381, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 88,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 486,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 364, + 365, 367, 368, 301, 440, 250, 485, 300, 126, 261, + 252, 204, 298, 236, 130, 329, 382, 331, 380, 384, + 330, 307, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 320, 321, 322, 305, 306, 383, 361, 360, 359, + 327, 328, 304, 332, 334, 304, 333, 350, 351, 348, + 349, 352, 353, 354, 355, 356,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767, 88,32767, + 284, 284, 284, 284,32767, 341, 342, 242, 242, 242, + 242,32767, 242, 285,32767,32767,32767,32767,32767,32767, + 32767, 433, 358, 336, 337, 335,32767, 411,32767,32767, + 32767,32767,32767, 413,32767, 88,32767,32767, 324, 326, + 405, 308,32767,32767, 90,32767,32767,32767,32767,32767, + 32767,32767,32767,32767, 408, 441, 441,32767,32767, 88, + 399, 88, 169, 223, 225, 174,32767, 416,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767, 346,32767, 496,32767, 441, + 32767,32767, 338, 339, 340,32767,32767, 441, 441,32767, + 441,32767, 441,32767,32767,32767, 174,32767,32767,32767, + 32767,32767,32767,32767, 90, 414, 414, 409, 174,32767, + 32767, 174, 87, 87, 87, 87, 174, 87, 187,32767, + 185, 185, 87, 88, 88, 87, 87, 189,32767, 455, + 189, 88, 87, 174, 87, 209, 209, 390, 176, 89, + 244, 244, 89, 390, 87, 174, 244, 88, 87, 87, + 244,32767,32767,32767, 82,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767, 401,32767,32767, 421,32767, 434, 453, 399,32767, + 344, 345, 347,32767, 443, 369, 370, 371, 372, 373, + 374, 375, 377,32767, 482, 404,32767,32767, 84, 117, + 260,32767, 494, 84, 402,32767, 494,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767, 84,32767, 84, + 32767,32767,32767,32767, 478,32767, 441,32767, 403,32767, + 343, 417, 460,32767,32767, 442,32767,32767, 84,32767, + 32767,32767,32767,32767,32767,32767,32767, 421,32767,32767, + 32767,32767,32767, 441,32767,32767,32767,32767,32767,32767, + 32767, 297,32767,32767,32767,32767,32767,32767, 441,32767, + 32767,32767,32767, 235,32767,32767,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767,32767, + 32767,32767, 82, 60,32767, 278,32767,32767,32767,32767, + 32767,32767,32767,32767,32767,32767,32767,32767,32767, 132, + 132, 3, 3, 132, 132, 132, 132, 132, 132, 132, + 132, 132, 132, 132, 132, 132, 263, 164, 263, 217, + 263, 263, 220, 209, 209, 270, 132, 132 + ); + + protected $goto = array( + 165, 165, 138, 138, 138, 148, 150, 181, 166, 163, + 163, 163, 163, 147, 164, 164, 164, 164, 164, 164, + 164, 147, 159, 160, 161, 162, 178, 176, 179, 420, + 421, 315, 422, 425, 426, 427, 428, 429, 430, 431, + 432, 888, 136, 139, 140, 141, 142, 143, 144, 145, + 146, 149, 175, 177, 180, 197, 200, 201, 203, 204, + 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 235, 236, 253, 254, 255, 322, 323, 324, 470, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 151, 196, 152, 167, 168, 169, 198, + 170, 153, 154, 155, 171, 156, 199, 137, 172, 157, + 173, 174, 158, 534, 202, 438, 736, 281, 471, 857, + 547, 7, 202, 526, 855, 472, 669, 231, 464, 232, + 233, 443, 443, 443, 671, 443, 464, 793, 774, 772, + 774, 569, 670, 436, 802, 797, 459, 456, 443, 545, + 572, 492, 494, 520, 524, 529, 530, 804, 537, 539, + 546, 800, 548, 424, 424, 424, 424, 424, 424, 424, + 424, 424, 424, 424, 424, 424, 424, 423, 423, 423, + 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, + 423, 485, 506, 443, 443, 488, 490, 540, 457, 478, + 443, 443, 974, 443, 768, 312, 543, 706, 444, 300, + 303, 450, 473, 474, 476, 469, 481, 733, 468, 487, + 487, 999, 999, 999, 999, 999, 999, 999, 999, 999, + 999, 999, 999, 701, 689, 831, 435, 835, 776, 697, + 1068, 1068, 779, 435, 263, 749, 482, 3, 4, 247, + 316, 827, 809, 449, 769, 975, 465, 1068, 460, 673, + 770, 770, 770, 770, 872, 1061, 764, 771, 705, 970, + 697, 1071, 697, 976, 1030, 378, 678, 298, 728, 723, + 724, 737, 679, 725, 676, 726, 727, 10, 1053, 677, + 507, 731, 462, 935, 823, 328, 508, 332, 319, 319, + 268, 269, 285, 466, 271, 327, 286, 330, 493, 807, + 807, 1058, 1069, 1069, 282, 283, 812, 688, 688, 816, + 1042, 512, 698, 698, 698, 700, 525, 687, 499, 1069, + 314, 287, 693, 279, 309, 690, 832, 576, 966, 514, + 370, 978, 971, 484, 817, 817, 817, 817, 978, 817, + 836, 817, 865, 702, 1039, 817, 781, 686, 874, 386, + 0, 1039, 0, 0, 0, 978, 978, 978, 978, 1050, + 1050, 978, 978, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 744, 0, 0, 745, 1036, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 834, 0, + 0, 834, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1043, 1044 + ); + + protected $gotoCheck = array( + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 60, 53, 8, 10, 76, 7, 7, + 7, 106, 53, 7, 7, 93, 13, 69, 81, 69, + 69, 8, 8, 8, 15, 8, 81, 13, 13, 13, + 13, 13, 14, 13, 13, 13, 8, 36, 8, 5, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 131, 131, 131, 131, 131, 131, 131, + 131, 131, 131, 131, 131, 131, 131, 129, 129, 129, + 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, + 129, 43, 43, 8, 8, 64, 64, 64, 8, 8, + 8, 8, 88, 8, 72, 72, 72, 33, 8, 46, + 46, 46, 46, 46, 46, 2, 2, 52, 8, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 11, 11, 11, 71, 11, 37, 23, + 139, 139, 11, 71, 128, 11, 11, 34, 34, 128, + 62, 90, 11, 62, 11, 88, 130, 139, 62, 10, + 71, 71, 71, 71, 11, 138, 71, 71, 11, 11, + 23, 139, 23, 88, 88, 62, 10, 49, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 62, 136, 10, + 51, 10, 50, 112, 86, 53, 53, 53, 53, 53, + 53, 53, 53, 53, 53, 53, 53, 53, 53, 81, + 81, 81, 140, 140, 76, 76, 84, 23, 23, 87, + 133, 65, 23, 23, 23, 23, 65, 23, 21, 140, + 65, 17, 27, 9, 16, 25, 92, 78, 118, 20, + 67, 60, 121, 68, 60, 60, 60, 60, 60, 60, + 95, 60, 106, 29, 93, 60, 75, 12, 109, 116, + -1, 93, -1, -1, -1, 60, 60, 60, 60, 93, + 93, 60, 60, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 60, -1, -1, 60, 93, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, + -1, 93, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, 93 + ); + + protected $gotoBase = array( + 0, 0, -336, 0, 0, 137, 0, 113, -141, 57, + -20, -120, -25, 124, 140, 132, 47, 75, 0, 0, + 4, 55, 0, -17, 0, 46, 0, 58, 0, -10, + -22, 0, 0, 198, -329, 0, -403, 220, 0, 0, + 0, 0, 0, 159, 0, 0, 172, 0, 0, 243, + 72, 73, 201, 79, 0, 0, 0, 0, 0, 0, + 107, 0, -98, 0, -43, -60, 0, -21, -27, -441, + 0, 2, -55, 0, 0, -15, -259, 0, 24, 0, + 0, 93, 3, 0, 74, 0, 50, 71, -95, 0, + 228, 0, 45, 120, 0, -14, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 109, 0, 0, -29, + 0, 0, 52, 0, 0, 0, -24, 0, -8, 0, + 0, 6, 0, 0, 0, 0, 0, 0, -13, -39, + 231, -53, 0, 70, 0, 0, 245, 0, 239, -6, + 66, 0, 0 + ); + + protected $gotoDefault = array( + -32768, 391, 579, 2, 580, 651, 659, 515, 411, 439, + 730, 877, 692, 712, 713, 714, 304, 342, 296, 302, + 500, 489, 382, 699, 354, 691, 379, 694, 353, 703, + 135, 516, 388, 707, 1, 709, 445, 740, 293, 717, + 294, 519, 719, 452, 721, 722, 299, 305, 306, 881, + 461, 486, 732, 205, 454, 734, 292, 735, 743, 333, + 297, 365, 522, 496, 477, 511, 412, 367, 483, 230, + 463, 985, 766, 374, 362, 780, 280, 788, 577, 796, + 799, 413, 414, 372, 811, 373, 821, 815, 993, 366, + 826, 355, 833, 1025, 357, 837, 840, 343, 502, 331, + 844, 845, 6, 849, 535, 536, 864, 243, 384, 873, + 352, 887, 346, 954, 956, 447, 381, 967, 361, 523, + 389, 972, 1029, 350, 415, 368, 270, 284, 246, 416, + 433, 251, 417, 369, 1032, 320, 1054, 434, 1062, 1070, + 277, 317, 480 + ); + + protected $ruleToNonTerminal = array( + 0, 1, 3, 3, 2, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 8, 8, 9, 10, 10, 11, 11, 12, + 12, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 17, 17, 18, 18, 18, 18, 20, 22, + 22, 16, 24, 24, 21, 26, 26, 23, 23, 25, + 25, 27, 27, 19, 28, 28, 29, 31, 32, 32, + 33, 34, 34, 36, 35, 35, 35, 35, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 13, 13, 56, 56, 59, 59, 58, 57, + 57, 50, 61, 61, 62, 62, 63, 63, 14, 15, + 15, 15, 66, 66, 66, 67, 67, 70, 70, 68, + 68, 72, 73, 73, 44, 44, 52, 52, 55, 55, + 55, 54, 74, 74, 75, 45, 45, 45, 45, 76, + 76, 77, 77, 78, 78, 42, 42, 38, 38, 79, + 40, 40, 80, 39, 39, 41, 41, 51, 51, 51, + 51, 64, 64, 83, 83, 84, 84, 86, 86, 87, + 87, 87, 85, 85, 65, 65, 88, 88, 89, 89, + 90, 90, 90, 47, 91, 91, 92, 48, 94, 94, + 95, 95, 69, 69, 96, 96, 96, 96, 101, 101, + 102, 102, 103, 103, 103, 103, 103, 104, 105, 105, + 100, 100, 97, 97, 99, 99, 107, 107, 106, 106, + 106, 106, 106, 106, 98, 108, 108, 109, 109, 49, + 110, 110, 43, 43, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 117, 111, 111, + 116, 116, 119, 120, 120, 121, 122, 122, 122, 71, + 71, 60, 60, 60, 112, 112, 112, 124, 124, 113, + 113, 115, 115, 115, 118, 118, 129, 129, 129, 82, + 131, 131, 131, 114, 114, 114, 114, 114, 114, 114, + 114, 114, 114, 114, 114, 114, 114, 114, 114, 46, + 46, 127, 127, 127, 123, 123, 123, 132, 132, 132, + 132, 132, 132, 53, 53, 53, 93, 93, 93, 93, + 134, 126, 126, 126, 126, 126, 126, 125, 125, 125, + 133, 133, 133, 133, 81, 135, 135, 136, 136, 136, + 136, 136, 130, 137, 137, 138, 138, 138, 138, 138, + 128, 128, 128, 128, 140, 141, 139, 139, 139, 139, + 139, 139, 139, 142, 142, 142, 142 + ); + + protected $ruleToLength = array( + 1, 1, 2, 0, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 3, 1, 1, 1, 0, 1, 0, + 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, + 2, 3, 1, 1, 7, 8, 6, 7, 2, 3, + 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, + 2, 1, 2, 2, 3, 1, 3, 2, 3, 1, + 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, + 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, + 3, 1, 2, 5, 7, 9, 5, 6, 3, 3, + 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, + 4, 2, 1, 3, 0, 1, 0, 1, 10, 7, + 6, 5, 1, 2, 2, 0, 2, 0, 2, 0, + 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, + 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, + 2, 4, 3, 1, 1, 1, 4, 0, 2, 5, + 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, + 1, 2, 0, 1, 3, 4, 6, 1, 2, 1, + 1, 1, 0, 1, 0, 2, 2, 4, 1, 3, + 1, 2, 2, 2, 3, 1, 1, 2, 3, 1, + 1, 3, 2, 0, 3, 4, 9, 3, 1, 3, + 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, + 1, 3, 1, 1, 0, 1, 1, 2, 1, 1, + 1, 1, 1, 1, 2, 1, 3, 1, 3, 2, + 3, 1, 0, 1, 1, 3, 3, 3, 4, 1, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, + 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, + 2, 1, 2, 4, 2, 10, 11, 7, 3, 2, + 0, 4, 2, 1, 3, 2, 2, 2, 4, 1, + 1, 1, 2, 3, 1, 1, 1, 1, 1, 0, + 3, 0, 1, 1, 0, 1, 1, 3, 3, 3, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 3, 0, + 1, 1, 3, 1, 1, 3, 1, 1, 4, 4, + 4, 1, 4, 1, 1, 3, 1, 4, 2, 2, + 3, 1, 4, 4, 3, 3, 3, 1, 3, 1, + 1, 3, 1, 1, 4, 3, 1, 1, 1, 3, + 3, 0, 1, 3, 1, 3, 1, 4, 2, 0, + 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, + 3, 6, 3, 1, 1, 2, 1 + ); + + protected function reduceRule0() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule1() { + $this->semValue = $this->handleNamespaces($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule2() { + if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; + } + + protected function reduceRule3() { + $this->semValue = array(); + } + + protected function reduceRule4() { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule5() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule6() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule7() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule8() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule9() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule10() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule11() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule12() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule13() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule14() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule15() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule16() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule17() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule18() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule19() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule20() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule21() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule22() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule23() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule24() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule25() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule26() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule27() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule28() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule29() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule30() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule31() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule32() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule33() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule34() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule35() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule36() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule37() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule38() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule39() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule40() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule41() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule42() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule43() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule44() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule45() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule46() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule47() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule48() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule49() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule50() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule51() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule52() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule53() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule54() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule55() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule56() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule57() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule58() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule59() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule60() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule61() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule62() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule63() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule64() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule65() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule66() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule67() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule68() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule69() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule70() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule71() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule72() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule73() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule74() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule75() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule76() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule77() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule78() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule79() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule80() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule81() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule82() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule83() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule84() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule85() { + /* nothing */ + } + + protected function reduceRule86() { + /* nothing */ + } + + protected function reduceRule87() { + /* nothing */ + } + + protected function reduceRule88() { + $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes)); + } + + protected function reduceRule89() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule90() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule91() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule92() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule93() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule94() { + $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule95() { + $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(3-2)], null, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule96() { + $this->semValue = new Stmt\Namespace_($this->semStack[$this->stackPos-(5-2)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule97() { + $this->semValue = new Stmt\Namespace_(null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED); + $this->checkNamespace($this->semValue); + } + + protected function reduceRule98() { + $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(3-2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule99() { + $this->semValue = new Stmt\Use_($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule100() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule101() { + $this->semValue = new Stmt\Const_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule102() { + $this->semValue = Stmt\Use_::TYPE_FUNCTION; + } + + protected function reduceRule103() { + $this->semValue = Stmt\Use_::TYPE_CONSTANT; + } + + protected function reduceRule104() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], $this->semStack[$this->stackPos-(7-2)], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule105() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(8-4)], $this->startAttributeStack[$this->stackPos-(8-4)] + $this->endAttributeStack[$this->stackPos-(8-4)]), $this->semStack[$this->stackPos-(8-7)], $this->semStack[$this->stackPos-(8-2)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); + } + + protected function reduceRule106() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-2)] + $this->endAttributeStack[$this->stackPos-(6-2)]), $this->semStack[$this->stackPos-(6-5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule107() { + $this->semValue = new Stmt\GroupUse(new Name($this->semStack[$this->stackPos-(7-3)], $this->startAttributeStack[$this->stackPos-(7-3)] + $this->endAttributeStack[$this->stackPos-(7-3)]), $this->semStack[$this->stackPos-(7-6)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule108() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule109() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule110() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule111() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule112() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule113() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule114() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule115() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule116() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule117() { + $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(1-1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(1-1)); + } + + protected function reduceRule118() { + $this->semValue = new Stmt\UseUse($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkUseUse($this->semValue, $this->stackPos-(3-3)); + } + + protected function reduceRule119() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule120() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule121() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $this->semValue->type = Stmt\Use_::TYPE_NORMAL; + } + + protected function reduceRule122() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; $this->semValue->type = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule123() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule124() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule125() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule126() { + $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule127() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule128() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule129() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule130() { + $this->semValue = new Node\Const_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule131() { + if (is_array($this->semStack[$this->stackPos-(2-2)])) { $this->semValue = array_merge($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); } else { $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; }; + } + + protected function reduceRule132() { + $this->semValue = array(); + } + + protected function reduceRule133() { + $startAttributes = $this->lookaheadStartAttributes; if (isset($startAttributes['comments'])) { $nop = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $nop = null; }; + if ($nop !== null) { $this->semStack[$this->stackPos-(1-1)][] = $nop; } $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule134() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule135() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule136() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule137() { + throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule138() { + + if ($this->semStack[$this->stackPos-(3-2)]) { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; $attrs = $this->startAttributeStack[$this->stackPos-(3-1)]; $stmts = $this->semValue; if (!empty($attrs['comments'])) {$stmts[0]->setAttribute('comments', array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', []))); }; + } else { + $startAttributes = $this->startAttributeStack[$this->stackPos-(3-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; }; + if (null === $this->semValue) { $this->semValue = array(); } + } + + } + + protected function reduceRule139() { + $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(7-3)], ['stmts' => is_array($this->semStack[$this->stackPos-(7-5)]) ? $this->semStack[$this->stackPos-(7-5)] : array($this->semStack[$this->stackPos-(7-5)]), 'elseifs' => $this->semStack[$this->stackPos-(7-6)], 'else' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule140() { + $this->semValue = new Stmt\If_($this->semStack[$this->stackPos-(10-3)], ['stmts' => $this->semStack[$this->stackPos-(10-6)], 'elseifs' => $this->semStack[$this->stackPos-(10-7)], 'else' => $this->semStack[$this->stackPos-(10-8)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); + } + + protected function reduceRule141() { + $this->semValue = new Stmt\While_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule142() { + $this->semValue = new Stmt\Do_($this->semStack[$this->stackPos-(7-5)], is_array($this->semStack[$this->stackPos-(7-2)]) ? $this->semStack[$this->stackPos-(7-2)] : array($this->semStack[$this->stackPos-(7-2)]), $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule143() { + $this->semValue = new Stmt\For_(['init' => $this->semStack[$this->stackPos-(9-3)], 'cond' => $this->semStack[$this->stackPos-(9-5)], 'loop' => $this->semStack[$this->stackPos-(9-7)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + } + + protected function reduceRule144() { + $this->semValue = new Stmt\Switch_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule145() { + $this->semValue = new Stmt\Break_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule146() { + $this->semValue = new Stmt\Continue_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule147() { + $this->semValue = new Stmt\Return_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule148() { + $this->semValue = new Stmt\Global_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule149() { + $this->semValue = new Stmt\Static_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule150() { + $this->semValue = new Stmt\Echo_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule151() { + $this->semValue = new Stmt\InlineHTML($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule152() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule153() { + $this->semValue = new Stmt\Unset_($this->semStack[$this->stackPos-(5-3)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule154() { + $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(7-3)], $this->semStack[$this->stackPos-(7-5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$this->stackPos-(7-5)][1], 'stmts' => $this->semStack[$this->stackPos-(7-7)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + } + + protected function reduceRule155() { + $this->semValue = new Stmt\Foreach_($this->semStack[$this->stackPos-(9-3)], $this->semStack[$this->stackPos-(9-7)][0], ['keyVar' => $this->semStack[$this->stackPos-(9-5)], 'byRef' => $this->semStack[$this->stackPos-(9-7)][1], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + } + + protected function reduceRule156() { + $this->semValue = new Stmt\Declare_($this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule157() { + $this->semValue = new Stmt\TryCatch($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-5)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkTryCatch($this->semValue); + } + + protected function reduceRule158() { + $this->semValue = new Stmt\Throw_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule159() { + $this->semValue = new Stmt\Goto_($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule160() { + $this->semValue = new Stmt\Label($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule161() { + $this->semValue = array(); /* means: no statement */ + } + + protected function reduceRule162() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule163() { + $startAttributes = $this->startAttributeStack[$this->stackPos-(1-1)]; if (isset($startAttributes['comments'])) { $this->semValue = new Stmt\Nop(['comments' => $startAttributes['comments']]); } else { $this->semValue = null; }; + if ($this->semValue === null) $this->semValue = array(); /* means: no statement */ + } + + protected function reduceRule164() { + $this->semValue = array(); + } + + protected function reduceRule165() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule166() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule167() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule168() { + $this->semValue = new Stmt\Catch_($this->semStack[$this->stackPos-(8-3)], substr($this->semStack[$this->stackPos-(8-4)], 1), $this->semStack[$this->stackPos-(8-7)], $this->startAttributeStack[$this->stackPos-(8-1)] + $this->endAttributes); + } + + protected function reduceRule169() { + $this->semValue = null; + } + + protected function reduceRule170() { + $this->semValue = new Stmt\Finally_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule171() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule172() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule173() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule174() { + $this->semValue = false; + } + + protected function reduceRule175() { + $this->semValue = true; + } + + protected function reduceRule176() { + $this->semValue = false; + } + + protected function reduceRule177() { + $this->semValue = true; + } + + protected function reduceRule178() { + $this->semValue = new Stmt\Function_($this->semStack[$this->stackPos-(10-3)], ['byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-5)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); + } + + protected function reduceRule179() { + $this->semValue = new Stmt\Class_($this->semStack[$this->stackPos-(7-2)], ['type' => $this->semStack[$this->stackPos-(7-1)], 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes); + $this->checkClass($this->semValue, $this->stackPos-(7-2)); + } + + protected function reduceRule180() { + $this->semValue = new Stmt\Interface_($this->semStack[$this->stackPos-(6-2)], ['extends' => $this->semStack[$this->stackPos-(6-3)], 'stmts' => $this->semStack[$this->stackPos-(6-5)]], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + $this->checkInterface($this->semValue, $this->stackPos-(6-2)); + } + + protected function reduceRule181() { + $this->semValue = new Stmt\Trait_($this->semStack[$this->stackPos-(5-2)], ['stmts' => $this->semStack[$this->stackPos-(5-4)]], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule182() { + $this->semValue = 0; + } + + protected function reduceRule183() { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + } + + protected function reduceRule184() { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + } + + protected function reduceRule185() { + $this->semValue = null; + } + + protected function reduceRule186() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule187() { + $this->semValue = array(); + } + + protected function reduceRule188() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule189() { + $this->semValue = array(); + } + + protected function reduceRule190() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule191() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule192() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule193() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule194() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule195() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule196() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule197() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule198() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule199() { + $this->semValue = null; + } + + protected function reduceRule200() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule201() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule202() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule203() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule204() { + $this->semValue = new Stmt\DeclareDeclare($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule205() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule206() { + $this->semValue = $this->semStack[$this->stackPos-(4-3)]; + } + + protected function reduceRule207() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule208() { + $this->semValue = $this->semStack[$this->stackPos-(5-3)]; + } + + protected function reduceRule209() { + $this->semValue = array(); + } + + protected function reduceRule210() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule211() { + $this->semValue = new Stmt\Case_($this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule212() { + $this->semValue = new Stmt\Case_(null, $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule213() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule214() { + $this->semValue = $this->semStack[$this->stackPos]; + } + + protected function reduceRule215() { + $this->semValue = is_array($this->semStack[$this->stackPos-(1-1)]) ? $this->semStack[$this->stackPos-(1-1)] : array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule216() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule217() { + $this->semValue = array(); + } + + protected function reduceRule218() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule219() { + $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(5-3)], is_array($this->semStack[$this->stackPos-(5-5)]) ? $this->semStack[$this->stackPos-(5-5)] : array($this->semStack[$this->stackPos-(5-5)]), $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule220() { + $this->semValue = array(); + } + + protected function reduceRule221() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule222() { + $this->semValue = new Stmt\ElseIf_($this->semStack[$this->stackPos-(6-3)], $this->semStack[$this->stackPos-(6-6)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule223() { + $this->semValue = null; + } + + protected function reduceRule224() { + $this->semValue = new Stmt\Else_(is_array($this->semStack[$this->stackPos-(2-2)]) ? $this->semStack[$this->stackPos-(2-2)] : array($this->semStack[$this->stackPos-(2-2)]), $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule225() { + $this->semValue = null; + } + + protected function reduceRule226() { + $this->semValue = new Stmt\Else_($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule227() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); + } + + protected function reduceRule228() { + $this->semValue = array($this->semStack[$this->stackPos-(2-2)], true); + } + + protected function reduceRule229() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); + } + + protected function reduceRule230() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)], false); + } + + protected function reduceRule231() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule232() { + $this->semValue = array(); + } + + protected function reduceRule233() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule234() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule235() { + $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(4-4)], 1), null, $this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-2)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkParam($this->semValue); + } + + protected function reduceRule236() { + $this->semValue = new Node\Param(substr($this->semStack[$this->stackPos-(6-4)], 1), $this->semStack[$this->stackPos-(6-6)], $this->semStack[$this->stackPos-(6-1)], $this->semStack[$this->stackPos-(6-2)], $this->semStack[$this->stackPos-(6-3)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); $this->checkParam($this->semValue); + } + + protected function reduceRule237() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule238() { + $this->semValue = new Node\NullableType($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule239() { + $this->semValue = $this->handleBuiltinTypes($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule240() { + $this->semValue = 'array'; + } + + protected function reduceRule241() { + $this->semValue = 'callable'; + } + + protected function reduceRule242() { + $this->semValue = null; + } + + protected function reduceRule243() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule244() { + $this->semValue = null; + } + + protected function reduceRule245() { + $this->semValue = $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule246() { + $this->semValue = array(); + } + + protected function reduceRule247() { + $this->semValue = $this->semStack[$this->stackPos-(4-2)]; + } + + protected function reduceRule248() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule249() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule250() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(1-1)], false, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule251() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], true, false, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule252() { + $this->semValue = new Node\Arg($this->semStack[$this->stackPos-(2-2)], false, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule253() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule254() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule255() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule256() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule257() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule258() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule259() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule260() { + $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule261() { + $this->semValue = new Stmt\StaticVar(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule262() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule263() { + $this->semValue = array(); + } + + protected function reduceRule264() { + $this->semValue = new Stmt\Property($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->checkProperty($this->semValue, $this->stackPos-(3-1)); + } + + protected function reduceRule265() { + $this->semValue = new Stmt\ClassConst($this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-1)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); $this->checkClassConst($this->semValue, $this->stackPos-(4-1)); + } + + protected function reduceRule266() { + $this->semValue = new Stmt\ClassMethod($this->semStack[$this->stackPos-(9-4)], ['type' => $this->semStack[$this->stackPos-(9-1)], 'byRef' => $this->semStack[$this->stackPos-(9-3)], 'params' => $this->semStack[$this->stackPos-(9-6)], 'returnType' => $this->semStack[$this->stackPos-(9-8)], 'stmts' => $this->semStack[$this->stackPos-(9-9)]], $this->startAttributeStack[$this->stackPos-(9-1)] + $this->endAttributes); + $this->checkClassMethod($this->semValue, $this->stackPos-(9-1)); + } + + protected function reduceRule267() { + $this->semValue = new Stmt\TraitUse($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule268() { + $this->semValue = array(); + } + + protected function reduceRule269() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule270() { + $this->semValue = array(); + } + + protected function reduceRule271() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule272() { + $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule273() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(5-1)][0], $this->semStack[$this->stackPos-(5-1)][1], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-4)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule274() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], $this->semStack[$this->stackPos-(4-3)], null, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule275() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule276() { + $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$this->stackPos-(4-1)][0], $this->semStack[$this->stackPos-(4-1)][1], null, $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule277() { + $this->semValue = array($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)]); + } + + protected function reduceRule278() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule279() { + $this->semValue = array(null, $this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule280() { + $this->semValue = null; + } + + protected function reduceRule281() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule282() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule283() { + $this->semValue = 0; + } + + protected function reduceRule284() { + $this->semValue = 0; + } + + protected function reduceRule285() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule286() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule287() { + $this->checkModifier($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->stackPos-(2-2)); $this->semValue = $this->semStack[$this->stackPos-(2-1)] | $this->semStack[$this->stackPos-(2-2)]; + } + + protected function reduceRule288() { + $this->semValue = Stmt\Class_::MODIFIER_PUBLIC; + } + + protected function reduceRule289() { + $this->semValue = Stmt\Class_::MODIFIER_PROTECTED; + } + + protected function reduceRule290() { + $this->semValue = Stmt\Class_::MODIFIER_PRIVATE; + } + + protected function reduceRule291() { + $this->semValue = Stmt\Class_::MODIFIER_STATIC; + } + + protected function reduceRule292() { + $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT; + } + + protected function reduceRule293() { + $this->semValue = Stmt\Class_::MODIFIER_FINAL; + } + + protected function reduceRule294() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule295() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule296() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule297() { + $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(1-1)], 1), null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule298() { + $this->semValue = new Stmt\PropertyProperty(substr($this->semStack[$this->stackPos-(3-1)], 1), $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule299() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule300() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule301() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule302() { + $this->semValue = array(); + } + + protected function reduceRule303() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule304() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule305() { + $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule306() { + $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule307() { + $this->semValue = new Expr\Assign($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule308() { + $this->semValue = new Expr\AssignRef($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule309() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule310() { + $this->semValue = new Expr\Clone_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule311() { + $this->semValue = new Expr\AssignOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule312() { + $this->semValue = new Expr\AssignOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule313() { + $this->semValue = new Expr\AssignOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule314() { + $this->semValue = new Expr\AssignOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule315() { + $this->semValue = new Expr\AssignOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule316() { + $this->semValue = new Expr\AssignOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule317() { + $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule318() { + $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule319() { + $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule320() { + $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule321() { + $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule322() { + $this->semValue = new Expr\AssignOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule323() { + $this->semValue = new Expr\PostInc($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule324() { + $this->semValue = new Expr\PreInc($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule325() { + $this->semValue = new Expr\PostDec($this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule326() { + $this->semValue = new Expr\PreDec($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule327() { + $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule328() { + $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule329() { + $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule330() { + $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule331() { + $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule332() { + $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule333() { + $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule334() { + $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule335() { + $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule336() { + $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule337() { + $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule338() { + $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule339() { + $this->semValue = new Expr\BinaryOp\Div($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule340() { + $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule341() { + $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule342() { + $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule343() { + $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule344() { + $this->semValue = new Expr\UnaryPlus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule345() { + $this->semValue = new Expr\UnaryMinus($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule346() { + $this->semValue = new Expr\BooleanNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule347() { + $this->semValue = new Expr\BitwiseNot($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule348() { + $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule349() { + $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule350() { + $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule351() { + $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule352() { + $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule353() { + $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule354() { + $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule355() { + $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule356() { + $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule357() { + $this->semValue = new Expr\Instanceof_($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule358() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule359() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(5-1)], $this->semStack[$this->stackPos-(5-3)], $this->semStack[$this->stackPos-(5-5)], $this->startAttributeStack[$this->stackPos-(5-1)] + $this->endAttributes); + } + + protected function reduceRule360() { + $this->semValue = new Expr\Ternary($this->semStack[$this->stackPos-(4-1)], null, $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule361() { + $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule362() { + $this->semValue = new Expr\Isset_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule363() { + $this->semValue = new Expr\Empty_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule364() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule365() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule366() { + $this->semValue = new Expr\Eval_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule367() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule368() { + $this->semValue = new Expr\Include_($this->semStack[$this->stackPos-(2-2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule369() { + $this->semValue = new Expr\Cast\Int_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule370() { + $this->semValue = new Expr\Cast\Double($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule371() { + $this->semValue = new Expr\Cast\String_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule372() { + $this->semValue = new Expr\Cast\Array_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule373() { + $this->semValue = new Expr\Cast\Object_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule374() { + $this->semValue = new Expr\Cast\Bool_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule375() { + $this->semValue = new Expr\Cast\Unset_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule376() { + $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; + $attrs['kind'] = strtolower($this->semStack[$this->stackPos-(2-1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE; + $this->semValue = new Expr\Exit_($this->semStack[$this->stackPos-(2-2)], $attrs); + } + + protected function reduceRule377() { + $this->semValue = new Expr\ErrorSuppress($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule378() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule379() { + $this->semValue = new Expr\ShellExec($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule380() { + $this->semValue = new Expr\Print_($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule381() { + $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule382() { + $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(2-2)], null, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule383() { + $this->semValue = new Expr\Yield_($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-2)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule384() { + $this->semValue = new Expr\YieldFrom($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule385() { + $this->semValue = new Expr\Closure(['static' => false, 'byRef' => $this->semStack[$this->stackPos-(10-2)], 'params' => $this->semStack[$this->stackPos-(10-4)], 'uses' => $this->semStack[$this->stackPos-(10-6)], 'returnType' => $this->semStack[$this->stackPos-(10-7)], 'stmts' => $this->semStack[$this->stackPos-(10-9)]], $this->startAttributeStack[$this->stackPos-(10-1)] + $this->endAttributes); + } + + protected function reduceRule386() { + $this->semValue = new Expr\Closure(['static' => true, 'byRef' => $this->semStack[$this->stackPos-(11-3)], 'params' => $this->semStack[$this->stackPos-(11-5)], 'uses' => $this->semStack[$this->stackPos-(11-7)], 'returnType' => $this->semStack[$this->stackPos-(11-8)], 'stmts' => $this->semStack[$this->stackPos-(11-10)]], $this->startAttributeStack[$this->stackPos-(11-1)] + $this->endAttributes); + } + + protected function reduceRule387() { + $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$this->stackPos-(7-3)], 'implements' => $this->semStack[$this->stackPos-(7-4)], 'stmts' => $this->semStack[$this->stackPos-(7-6)]], $this->startAttributeStack[$this->stackPos-(7-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(7-2)]); + $this->checkClass($this->semValue[0], -1); + } + + protected function reduceRule388() { + $this->semValue = new Expr\New_($this->semStack[$this->stackPos-(3-2)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule389() { + list($class, $ctorArgs) = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule390() { + $this->semValue = array(); + } + + protected function reduceRule391() { + $this->semValue = $this->semStack[$this->stackPos-(4-3)]; + } + + protected function reduceRule392() { + $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule393() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule394() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule395() { + $this->semValue = new Expr\ClosureUse(substr($this->semStack[$this->stackPos-(2-2)], 1), $this->semStack[$this->stackPos-(2-1)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule396() { + $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule397() { + $this->semValue = new Expr\FuncCall($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule398() { + $this->semValue = new Expr\StaticCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule399() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule400() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule401() { + $this->semValue = new Name($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule402() { + $this->semValue = new Name\FullyQualified($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule403() { + $this->semValue = new Name\Relative($this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule404() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule405() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule406() { + $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + } + + protected function reduceRule407() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule408() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule409() { + $this->semValue = null; + } + + protected function reduceRule410() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule411() { + $this->semValue = array(); + } + + protected function reduceRule412() { + $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$this->stackPos-(1-1)], '`'), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes)); + } + + protected function reduceRule413() { + foreach ($this->semStack[$this->stackPos-(1-1)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', true); } }; $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule414() { + $this->semValue = array(); + } + + protected function reduceRule415() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule416() { + $this->semValue = new Expr\ConstFetch($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule417() { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule418() { + $this->semValue = new Expr\ClassConstFetch($this->semStack[$this->stackPos-(3-1)], new Expr\Error($this->startAttributeStack[$this->stackPos-(3-3)] + $this->endAttributeStack[$this->stackPos-(3-3)]), $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); $this->errorState = 2; + } + + protected function reduceRule419() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_SHORT; + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule420() { + $attrs = $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes; $attrs['kind'] = Expr\Array_::KIND_LONG; + $this->semValue = new Expr\Array_($this->semStack[$this->stackPos-(4-3)], $attrs); + } + + protected function reduceRule421() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule422() { + $attrs = $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes; $attrs['kind'] = ($this->semStack[$this->stackPos-(1-1)][0] === "'" || ($this->semStack[$this->stackPos-(1-1)][1] === "'" && ($this->semStack[$this->stackPos-(1-1)][0] === 'b' || $this->semStack[$this->stackPos-(1-1)][0] === 'B')) ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED); + $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$this->stackPos-(1-1)]), $attrs); + } + + protected function reduceRule423() { + $this->semValue = $this->parseLNumber($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule424() { + $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$this->stackPos-(1-1)]), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule425() { + $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule426() { + $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule427() { + $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule428() { + $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule429() { + $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule430() { + $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule431() { + $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule432() { + $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule433() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule434() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule435() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; + $this->semValue = new Scalar\String_(Scalar\String_::parseDocString($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-2)]), $attrs); + } + + protected function reduceRule436() { + $attrs = $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(2-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(2-1)], $matches); $attrs['docLabel'] = $matches[1];; + $this->semValue = new Scalar\String_('', $attrs); + } + + protected function reduceRule437() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED; + foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', true); } }; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule438() { + $attrs = $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes; $attrs['kind'] = strpos($this->semStack[$this->stackPos-(3-1)], "'") === false ? Scalar\String_::KIND_HEREDOC : Scalar\String_::KIND_NOWDOC; preg_match('/\A[bB]?<<<[ \t]*[\'"]?([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)[\'"]?(?:\r\n|\n|\r)\z/', $this->semStack[$this->stackPos-(3-1)], $matches); $attrs['docLabel'] = $matches[1];; + foreach ($this->semStack[$this->stackPos-(3-2)] as $s) { if ($s instanceof Node\Scalar\EncapsedStringPart) { $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, null, true); } } $s->value = preg_replace('~(\r\n|\n|\r)\z~', '', $s->value); if ('' === $s->value) array_pop($this->semStack[$this->stackPos-(3-2)]);; $this->semValue = new Scalar\Encapsed($this->semStack[$this->stackPos-(3-2)], $attrs); + } + + protected function reduceRule439() { + $this->semValue = null; + } + + protected function reduceRule440() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule441() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule442() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule443() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule444() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule445() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule446() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule447() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule448() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule449() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule450() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule451() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule452() { + $this->semValue = new Expr\MethodCall($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->semStack[$this->stackPos-(4-4)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule453() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule454() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule455() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule456() { + $this->semValue = substr($this->semStack[$this->stackPos-(1-1)], 1); + } + + protected function reduceRule457() { + $this->semValue = $this->semStack[$this->stackPos-(4-3)]; + } + + protected function reduceRule458() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule459() { + $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); $this->errorState = 2; + } + + protected function reduceRule460() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule461() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule462() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule463() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule464() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule465() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule466() { + $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule467() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule468() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule469() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule470() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule471() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule472() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule473() { + $this->semValue = new Expr\Error($this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); $this->errorState = 2; + } + + protected function reduceRule474() { + $this->semValue = new Expr\List_($this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule475() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule476() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule477() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule478() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule479() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule480() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule481() { + $this->semValue = null; + } + + protected function reduceRule482() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; $end = count($this->semValue)-1; if ($this->semValue[$end] === null) unset($this->semValue[$end]); + } + + protected function reduceRule483() { + $this->semStack[$this->stackPos-(3-1)][] = $this->semStack[$this->stackPos-(3-3)]; $this->semValue = $this->semStack[$this->stackPos-(3-1)]; + } + + protected function reduceRule484() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule485() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(3-3)], $this->semStack[$this->stackPos-(3-1)], false, $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule486() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(1-1)], null, false, $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule487() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(4-4)], $this->semStack[$this->stackPos-(4-1)], true, $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule488() { + $this->semValue = new Expr\ArrayItem($this->semStack[$this->stackPos-(2-2)], null, true, $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule489() { + $this->semValue = null; + } + + protected function reduceRule490() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule491() { + $this->semStack[$this->stackPos-(2-1)][] = $this->semStack[$this->stackPos-(2-2)]; $this->semValue = $this->semStack[$this->stackPos-(2-1)]; + } + + protected function reduceRule492() { + $this->semValue = array($this->semStack[$this->stackPos-(1-1)]); + } + + protected function reduceRule493() { + $this->semValue = array($this->semStack[$this->stackPos-(2-1)], $this->semStack[$this->stackPos-(2-2)]); + } + + protected function reduceRule494() { + $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule495() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule496() { + $this->semValue = $this->semStack[$this->stackPos-(1-1)]; + } + + protected function reduceRule497() { + $this->semValue = new Expr\ArrayDimFetch($this->semStack[$this->stackPos-(4-1)], $this->semStack[$this->stackPos-(4-3)], $this->startAttributeStack[$this->stackPos-(4-1)] + $this->endAttributes); + } + + protected function reduceRule498() { + $this->semValue = new Expr\PropertyFetch($this->semStack[$this->stackPos-(3-1)], $this->semStack[$this->stackPos-(3-3)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule499() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule500() { + $this->semValue = new Expr\Variable($this->semStack[$this->stackPos-(3-2)], $this->startAttributeStack[$this->stackPos-(3-1)] + $this->endAttributes); + } + + protected function reduceRule501() { + $this->semValue = new Expr\ArrayDimFetch(new Expr\Variable($this->semStack[$this->stackPos-(6-2)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes), $this->semStack[$this->stackPos-(6-4)], $this->startAttributeStack[$this->stackPos-(6-1)] + $this->endAttributes); + } + + protected function reduceRule502() { + $this->semValue = $this->semStack[$this->stackPos-(3-2)]; + } + + protected function reduceRule503() { + $this->semValue = new Scalar\String_($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule504() { + $this->semValue = $this->parseNumString($this->semStack[$this->stackPos-(1-1)], $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } + + protected function reduceRule505() { + $this->semValue = $this->parseNumString('-' . $this->semStack[$this->stackPos-(2-2)], $this->startAttributeStack[$this->stackPos-(2-1)] + $this->endAttributes); + } + + protected function reduceRule506() { + $this->semValue = new Expr\Variable(substr($this->semStack[$this->stackPos-(1-1)], 1), $this->startAttributeStack[$this->stackPos-(1-1)] + $this->endAttributes); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php new file mode 100644 index 0000000..861663f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Parser/Tokens.php @@ -0,0 +1,144 @@ +lexer = $lexer; + $this->errors = array(); + + if (isset($options['throwOnError'])) { + throw new \LogicException( + '"throwOnError" is no longer supported, use "errorHandler" instead'); + } + } + + /** + * Parses PHP code into a node tree. + * + * If a non-throwing error handler is used, the parser will continue parsing after an error + * occurred and attempt to build a partial AST. + * + * @param string $code The source code to parse + * @param ErrorHandler|null $errorHandler Error handler to use for lexer/parser errors, defaults + * to ErrorHandler\Throwing. + * + * @return Node[]|null Array of statements (or null if the 'throwOnError' option is disabled and the parser was + * unable to recover from an error). + */ + public function parse($code, ErrorHandler $errorHandler = null) { + $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing; + + // Initialize the lexer + $this->lexer->startLexing($code, $this->errorHandler); + + // We start off with no lookahead-token + $symbol = self::SYMBOL_NONE; + + // The attributes for a node are taken from the first and last token of the node. + // From the first token only the startAttributes are taken and from the last only + // the endAttributes. Both are merged using the array union operator (+). + $startAttributes = '*POISON'; + $endAttributes = '*POISON'; + $this->endAttributes = $endAttributes; + + // Keep stack of start and end attributes + $this->startAttributeStack = array(); + $this->endAttributeStack = array($endAttributes); + + // Start off in the initial state and keep a stack of previous states + $state = 0; + $stateStack = array($state); + + // Semantic value stack (contains values of tokens and semantic action results) + $this->semStack = array(); + + // Current position in the stack(s) + $this->stackPos = 0; + + $this->errorState = 0; + + for (;;) { + //$this->traceNewState($state, $symbol); + + if ($this->actionBase[$state] == 0) { + $rule = $this->actionDefault[$state]; + } else { + if ($symbol === self::SYMBOL_NONE) { + // Fetch the next token id from the lexer and fetch additional info by-ref. + // The end attributes are fetched into a temporary variable and only set once the token is really + // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is + // reduced after a token was read but not yet shifted. + $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes); + + // map the lexer token id to the internally used symbols + $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize + ? $this->tokenToSymbol[$tokenId] + : $this->invalidSymbol; + + if ($symbol === $this->invalidSymbol) { + throw new \RangeException(sprintf( + 'The lexer returned an invalid token (id=%d, value=%s)', + $tokenId, $tokenValue + )); + } + + // This is necessary to assign some meaningful attributes to /* empty */ productions. They'll get + // the attributes of the next token, even though they don't contain it themselves. + $this->startAttributeStack[$this->stackPos+1] = $startAttributes; + $this->endAttributeStack[$this->stackPos+1] = $endAttributes; + $this->lookaheadStartAttributes = $startAttributes; + + //$this->traceRead($symbol); + } + + $idx = $this->actionBase[$state] + $symbol; + if ((($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $symbol)) + && ($action = $this->action[$idx]) != $this->defaultAction) { + /* + * >= YYNLSTATES: shift and reduce + * > 0: shift + * = 0: accept + * < 0: reduce + * = -YYUNEXPECTED: error + */ + if ($action > 0) { + /* shift */ + //$this->traceShift($symbol); + + ++$this->stackPos; + $stateStack[$this->stackPos] = $state = $action; + $this->semStack[$this->stackPos] = $tokenValue; + $this->startAttributeStack[$this->stackPos] = $startAttributes; + $this->endAttributeStack[$this->stackPos] = $endAttributes; + $this->endAttributes = $endAttributes; + $symbol = self::SYMBOL_NONE; + + if ($this->errorState) { + --$this->errorState; + } + + if ($action < $this->YYNLSTATES) { + continue; + } + + /* $yyn >= YYNLSTATES means shift-and-reduce */ + $rule = $action - $this->YYNLSTATES; + } else { + $rule = -$action; + } + } else { + $rule = $this->actionDefault[$state]; + } + } + + for (;;) { + if ($rule === 0) { + /* accept */ + //$this->traceAccept(); + return $this->semValue; + } elseif ($rule !== $this->unexpectedTokenRule) { + /* reduce */ + //$this->traceReduce($rule); + + try { + $this->{'reduceRule' . $rule}(); + } catch (Error $e) { + if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) { + $e->setStartLine($startAttributes['startLine']); + } + + $this->emitError($e); + // Can't recover from this type of error + return null; + } + + /* Goto - shift nonterminal */ + $lastEndAttributes = $this->endAttributeStack[$this->stackPos]; + $this->stackPos -= $this->ruleToLength[$rule]; + $nonTerminal = $this->ruleToNonTerminal[$rule]; + $idx = $this->gotoBase[$nonTerminal] + $stateStack[$this->stackPos]; + if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] == $nonTerminal) { + $state = $this->goto[$idx]; + } else { + $state = $this->gotoDefault[$nonTerminal]; + } + + ++$this->stackPos; + $stateStack[$this->stackPos] = $state; + $this->semStack[$this->stackPos] = $this->semValue; + $this->endAttributeStack[$this->stackPos] = $lastEndAttributes; + } else { + /* error */ + switch ($this->errorState) { + case 0: + $msg = $this->getErrorMessage($symbol, $state); + $this->emitError(new Error($msg, $startAttributes + $endAttributes)); + // Break missing intentionally + case 1: + case 2: + $this->errorState = 3; + + // Pop until error-expecting state uncovered + while (!( + (($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol) + || ($state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $this->errorSymbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] == $this->errorSymbol) + ) || ($action = $this->action[$idx]) == $this->defaultAction) { // Not totally sure about this + if ($this->stackPos <= 0) { + // Could not recover from error + return null; + } + $state = $stateStack[--$this->stackPos]; + //$this->tracePop($state); + } + + //$this->traceShift($this->errorSymbol); + ++$this->stackPos; + $stateStack[$this->stackPos] = $state = $action; + + // We treat the error symbol as being empty, so we reset the end attributes + // to the end attributes of the last non-error symbol + $this->endAttributeStack[$this->stackPos] = $this->endAttributeStack[$this->stackPos - 1]; + $this->endAttributes = $this->endAttributeStack[$this->stackPos - 1]; + break; + + case 3: + if ($symbol === 0) { + // Reached EOF without recovering from error + return null; + } + + //$this->traceDiscard($symbol); + $symbol = self::SYMBOL_NONE; + break 2; + } + } + + if ($state < $this->YYNLSTATES) { + break; + } + + /* >= YYNLSTATES means shift-and-reduce */ + $rule = $state - $this->YYNLSTATES; + } + } + + throw new \RuntimeException('Reached end of parser loop'); + } + + protected function emitError(Error $error) { + $this->errorHandler->handleError($error); + } + + protected function getErrorMessage($symbol, $state) { + $expectedString = ''; + if ($expected = $this->getExpectedTokens($state)) { + $expectedString = ', expecting ' . implode(' or ', $expected); + } + + return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString; + } + + protected function getExpectedTokens($state) { + $expected = array(); + + $base = $this->actionBase[$state]; + foreach ($this->symbolToName as $symbol => $name) { + $idx = $base + $symbol; + if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + || $state < $this->YY2TBLSTATE + && ($idx = $this->actionBase[$state + $this->YYNLSTATES] + $symbol) >= 0 + && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol + ) { + if ($this->action[$idx] != $this->unexpectedTokenRule + && $this->action[$idx] != $this->defaultAction + && $symbol != $this->errorSymbol + ) { + if (count($expected) == 4) { + /* Too many expected tokens */ + return array(); + } + + $expected[] = $name; + } + } + } + + return $expected; + } + + /* + * Tracing functions used for debugging the parser. + */ + + /* + protected function traceNewState($state, $symbol) { + echo '% State ' . $state + . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n"; + } + + protected function traceRead($symbol) { + echo '% Reading ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceShift($symbol) { + echo '% Shift ' . $this->symbolToName[$symbol] . "\n"; + } + + protected function traceAccept() { + echo "% Accepted.\n"; + } + + protected function traceReduce($n) { + echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n"; + } + + protected function tracePop($state) { + echo '% Recovering, uncovered state ' . $state . "\n"; + } + + protected function traceDiscard($symbol) { + echo '% Discard ' . $this->symbolToName[$symbol] . "\n"; + } + */ + + /* + * Helper functions invoked by semantic actions + */ + + /** + * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions. + * + * @param Node[] $stmts + * @return Node[] + */ + protected function handleNamespaces(array $stmts) { + $hasErrored = false; + $style = $this->getNamespacingStyle($stmts); + if (null === $style) { + // not namespaced, nothing to do + return $stmts; + } elseif ('brace' === $style) { + // For braced namespaces we only have to check that there are no invalid statements between the namespaces + $afterFirstNamespace = false; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $afterFirstNamespace = true; + } elseif (!$stmt instanceof Node\Stmt\HaltCompiler + && !$stmt instanceof Node\Stmt\Nop + && $afterFirstNamespace && !$hasErrored) { + $this->emitError(new Error( + 'No code may exist outside of namespace {}', $stmt->getAttributes())); + $hasErrored = true; // Avoid one error for every statement + } + } + return $stmts; + } else { + // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts + $resultStmts = array(); + $targetStmts =& $resultStmts; + foreach ($stmts as $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + if ($stmt->stmts === null) { + $stmt->stmts = array(); + $targetStmts =& $stmt->stmts; + $resultStmts[] = $stmt; + } else { + // This handles the invalid case of mixed style namespaces + $resultStmts[] = $stmt; + $targetStmts =& $resultStmts; + } + } elseif ($stmt instanceof Node\Stmt\HaltCompiler) { + // __halt_compiler() is not moved into the namespace + $resultStmts[] = $stmt; + } else { + $targetStmts[] = $stmt; + } + } + return $resultStmts; + } + } + + private function getNamespacingStyle(array $stmts) { + $style = null; + $hasNotAllowedStmts = false; + foreach ($stmts as $i => $stmt) { + if ($stmt instanceof Node\Stmt\Namespace_) { + $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace'; + if (null === $style) { + $style = $currentStyle; + if ($hasNotAllowedStmts) { + $this->emitError(new Error( + 'Namespace declaration statement has to be the very first statement in the script', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + } + } elseif ($style !== $currentStyle) { + $this->emitError(new Error( + 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', + $stmt->getLine() // Avoid marking the entire namespace as an error + )); + // Treat like semicolon style for namespace normalization + return 'semicolon'; + } + continue; + } + + /* declare(), __halt_compiler() and nops can be used before a namespace declaration */ + if ($stmt instanceof Node\Stmt\Declare_ + || $stmt instanceof Node\Stmt\HaltCompiler + || $stmt instanceof Node\Stmt\Nop) { + continue; + } + + /* There may be a hashbang line at the very start of the file */ + if ($i == 0 && $stmt instanceof Node\Stmt\InlineHTML && preg_match('/\A#!.*\r?\n\z/', $stmt->value)) { + continue; + } + + /* Everything else if forbidden before namespace declarations */ + $hasNotAllowedStmts = true; + } + return $style; + } + + protected function handleBuiltinTypes(Name $name) { + $scalarTypes = [ + 'bool' => true, + 'int' => true, + 'float' => true, + 'string' => true, + 'iterable' => true, + 'void' => true, + 'object' => true, + ]; + + if (!$name->isUnqualified()) { + return $name; + } + + $lowerName = strtolower($name->toString()); + return isset($scalarTypes[$lowerName]) ? $lowerName : $name; + } + + protected static $specialNames = array( + 'self' => true, + 'parent' => true, + 'static' => true, + ); + + protected function getAttributesAt($pos) { + return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos]; + } + + protected function parseLNumber($str, $attributes, $allowInvalidOctal = false) { + try { + return LNumber::fromString($str, $attributes, $allowInvalidOctal); + } catch (Error $error) { + $this->emitError($error); + // Use dummy value + return new LNumber(0, $attributes); + } + } + + protected function parseNumString($str, $attributes) { + if (!preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) { + return new String_($str, $attributes); + } + + $num = +$str; + if (!is_int($num)) { + return new String_($str, $attributes); + } + + return new LNumber($num, $attributes); + } + + protected function checkModifier($a, $b, $modifierPos) { + // Jumping through some hoops here because verifyModifier() is also used elsewhere + try { + Class_::verifyModifier($a, $b); + } catch (Error $error) { + $error->setAttributes($this->getAttributesAt($modifierPos)); + $this->emitError($error); + } + } + + protected function checkParam(Param $node) { + if ($node->variadic && null !== $node->default) { + $this->emitError(new Error( + 'Variadic parameter cannot have a default value', + $node->default->getAttributes() + )); + } + } + + protected function checkTryCatch(TryCatch $node) { + if (empty($node->catches) && null === $node->finally) { + $this->emitError(new Error( + 'Cannot use try without catch or finally', $node->getAttributes() + )); + } + } + + protected function checkNamespace(Namespace_ $node) { + if (isset(self::$specialNames[strtolower($node->name)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as namespace name', $node->name), + $node->name->getAttributes() + )); + } + + if (null !== $node->stmts) { + foreach ($node->stmts as $stmt) { + if ($stmt instanceof Namespace_) { + $this->emitError(new Error( + 'Namespace declarations cannot be nested', $stmt->getAttributes() + )); + } + } + } + } + + protected function checkClass(Class_ $node, $namePos) { + if (null !== $node->name && isset(self::$specialNames[strtolower($node->name)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name), + $this->getAttributesAt($namePos) + )); + } + + if (isset(self::$specialNames[strtolower($node->extends)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), + $node->extends->getAttributes() + )); + } + + foreach ($node->implements as $interface) { + if (isset(self::$specialNames[strtolower($interface)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), + $interface->getAttributes() + )); + } + } + } + + protected function checkInterface(Interface_ $node, $namePos) { + if (null !== $node->name && isset(self::$specialNames[strtolower($node->name)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as class name as it is reserved', $node->name), + $this->getAttributesAt($namePos) + )); + } + + foreach ($node->extends as $interface) { + if (isset(self::$specialNames[strtolower($interface)])) { + $this->emitError(new Error( + sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), + $interface->getAttributes() + )); + } + } + } + + protected function checkClassMethod(ClassMethod $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + switch (strtolower($node->name)) { + case '__construct': + $this->emitError(new Error( + sprintf('Constructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__destruct': + $this->emitError(new Error( + sprintf('Destructor %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + case '__clone': + $this->emitError(new Error( + sprintf('Clone method %s() cannot be static', $node->name), + $this->getAttributesAt($modifierPos))); + break; + } + } + } + + protected function checkClassConst(ClassConst $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_STATIC) { + $this->emitError(new Error( + "Cannot use 'static' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error( + "Cannot use 'abstract' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + if ($node->flags & Class_::MODIFIER_FINAL) { + $this->emitError(new Error( + "Cannot use 'final' as constant modifier", + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkProperty(Property $node, $modifierPos) { + if ($node->flags & Class_::MODIFIER_ABSTRACT) { + $this->emitError(new Error('Properties cannot be declared abstract', + $this->getAttributesAt($modifierPos))); + } + + if ($node->flags & Class_::MODIFIER_FINAL) { + $this->emitError(new Error('Properties cannot be declared final', + $this->getAttributesAt($modifierPos))); + } + } + + protected function checkUseUse(UseUse $node, $namePos) { + if ('self' == strtolower($node->alias) || 'parent' == strtolower($node->alias)) { + $this->emitError(new Error( + sprintf( + 'Cannot use %s as %s because \'%2$s\' is a special class name', + $node->name, $node->alias + ), + $this->getAttributesAt($namePos) + )); + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php new file mode 100644 index 0000000..28b9070 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php @@ -0,0 +1,43 @@ +type ? $this->pType($node->type) . ' ' : '') + . ($node->byRef ? '&' : '') + . ($node->variadic ? '...' : '') + . '$' . $node->name + . ($node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pArg(Node\Arg $node) { + return ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value); + } + + protected function pConst(Node\Const_ $node) { + return $node->name . ' = ' . $this->p($node->value); + } + + protected function pNullableType(Node\NullableType $node) { + return '?' . $this->pType($node->type); + } + + // Names + + protected function pName(Name $node) { + return implode('\\', $node->parts); + } + + protected function pName_FullyQualified(Name\FullyQualified $node) { + return '\\' . implode('\\', $node->parts); + } + + protected function pName_Relative(Name\Relative $node) { + return 'namespace\\' . implode('\\', $node->parts); + } + + // Magic Constants + + protected function pScalar_MagicConst_Class(MagicConst\Class_ $node) { + return '__CLASS__'; + } + + protected function pScalar_MagicConst_Dir(MagicConst\Dir $node) { + return '__DIR__'; + } + + protected function pScalar_MagicConst_File(MagicConst\File $node) { + return '__FILE__'; + } + + protected function pScalar_MagicConst_Function(MagicConst\Function_ $node) { + return '__FUNCTION__'; + } + + protected function pScalar_MagicConst_Line(MagicConst\Line $node) { + return '__LINE__'; + } + + protected function pScalar_MagicConst_Method(MagicConst\Method $node) { + return '__METHOD__'; + } + + protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node) { + return '__NAMESPACE__'; + } + + protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node) { + return '__TRAIT__'; + } + + // Scalars + + protected function pScalar_String(Scalar\String_ $node) { + $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED); + switch ($kind) { + case Scalar\String_::KIND_NOWDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return $this->pNoIndent("<<<'$label'\n$label") . $this->docStringEndToken; + } + + return $this->pNoIndent("<<<'$label'\n$node->value\n$label") + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_SINGLE_QUOTED: + return '\'' . $this->pNoIndent(addcslashes($node->value, '\'\\')) . '\''; + case Scalar\String_::KIND_HEREDOC: + $label = $node->getAttribute('docLabel'); + if ($label && !$this->containsEndLabel($node->value, $label)) { + if ($node->value === '') { + return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken; + } + + $escaped = $this->escapeString($node->value, null); + return $this->pNoIndent("<<<$label\n" . $escaped ."\n$label") + . $this->docStringEndToken; + } + /* break missing intentionally */ + case Scalar\String_::KIND_DOUBLE_QUOTED: + return '"' . $this->escapeString($node->value, '"') . '"'; + } + throw new \Exception('Invalid string kind'); + } + + protected function pScalar_Encapsed(Scalar\Encapsed $node) { + if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) { + $label = $node->getAttribute('docLabel'); + if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) { + if (count($node->parts) === 1 + && $node->parts[0] instanceof Scalar\EncapsedStringPart + && $node->parts[0]->value === '' + ) { + return $this->pNoIndent("<<<$label\n$label") . $this->docStringEndToken; + } + + return $this->pNoIndent( + "<<<$label\n" . $this->pEncapsList($node->parts, null) . "\n$label" + ) . $this->docStringEndToken; + } + } + return '"' . $this->pEncapsList($node->parts, '"') . '"'; + } + + protected function pScalar_LNumber(Scalar\LNumber $node) { + if ($node->value === -\PHP_INT_MAX-1) { + // PHP_INT_MIN cannot be represented as a literal, + // because the sign is not part of the literal + return '(-' . \PHP_INT_MAX . '-1)'; + } + + $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC); + if (Scalar\LNumber::KIND_DEC === $kind) { + return (string) $node->value; + } + + $sign = $node->value < 0 ? '-' : ''; + $str = (string) $node->value; + switch ($kind) { + case Scalar\LNumber::KIND_BIN: + return $sign . '0b' . base_convert($str, 10, 2); + case Scalar\LNumber::KIND_OCT: + return $sign . '0' . base_convert($str, 10, 8); + case Scalar\LNumber::KIND_HEX: + return $sign . '0x' . base_convert($str, 10, 16); + } + throw new \Exception('Invalid number kind'); + } + + protected function pScalar_DNumber(Scalar\DNumber $node) { + if (!is_finite($node->value)) { + if ($node->value === \INF) { + return '\INF'; + } elseif ($node->value === -\INF) { + return '-\INF'; + } else { + return '\NAN'; + } + } + + // Try to find a short full-precision representation + $stringValue = sprintf('%.16G', $node->value); + if ($node->value !== (double) $stringValue) { + $stringValue = sprintf('%.17G', $node->value); + } + + // %G is locale dependent and there exists no locale-independent alternative. We don't want + // mess with switching locales here, so let's assume that a comma is the only non-standard + // decimal separator we may encounter... + $stringValue = str_replace(',', '.', $stringValue); + + // ensure that number is really printed as float + return preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue; + } + + // Assignments + + protected function pExpr_Assign(Expr\Assign $node) { + return $this->pInfixOp('Expr_Assign', $node->var, ' = ', $node->expr); + } + + protected function pExpr_AssignRef(Expr\AssignRef $node) { + return $this->pInfixOp('Expr_AssignRef', $node->var, ' =& ', $node->expr); + } + + protected function pExpr_AssignOp_Plus(AssignOp\Plus $node) { + return $this->pInfixOp('Expr_AssignOp_Plus', $node->var, ' += ', $node->expr); + } + + protected function pExpr_AssignOp_Minus(AssignOp\Minus $node) { + return $this->pInfixOp('Expr_AssignOp_Minus', $node->var, ' -= ', $node->expr); + } + + protected function pExpr_AssignOp_Mul(AssignOp\Mul $node) { + return $this->pInfixOp('Expr_AssignOp_Mul', $node->var, ' *= ', $node->expr); + } + + protected function pExpr_AssignOp_Div(AssignOp\Div $node) { + return $this->pInfixOp('Expr_AssignOp_Div', $node->var, ' /= ', $node->expr); + } + + protected function pExpr_AssignOp_Concat(AssignOp\Concat $node) { + return $this->pInfixOp('Expr_AssignOp_Concat', $node->var, ' .= ', $node->expr); + } + + protected function pExpr_AssignOp_Mod(AssignOp\Mod $node) { + return $this->pInfixOp('Expr_AssignOp_Mod', $node->var, ' %= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node) { + return $this->pInfixOp('Expr_AssignOp_BitwiseAnd', $node->var, ' &= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node) { + return $this->pInfixOp('Expr_AssignOp_BitwiseOr', $node->var, ' |= ', $node->expr); + } + + protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node) { + return $this->pInfixOp('Expr_AssignOp_BitwiseXor', $node->var, ' ^= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node) { + return $this->pInfixOp('Expr_AssignOp_ShiftLeft', $node->var, ' <<= ', $node->expr); + } + + protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node) { + return $this->pInfixOp('Expr_AssignOp_ShiftRight', $node->var, ' >>= ', $node->expr); + } + + protected function pExpr_AssignOp_Pow(AssignOp\Pow $node) { + return $this->pInfixOp('Expr_AssignOp_Pow', $node->var, ' **= ', $node->expr); + } + + // Binary expressions + + protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node) { + return $this->pInfixOp('Expr_BinaryOp_Plus', $node->left, ' + ', $node->right); + } + + protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node) { + return $this->pInfixOp('Expr_BinaryOp_Minus', $node->left, ' - ', $node->right); + } + + protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node) { + return $this->pInfixOp('Expr_BinaryOp_Mul', $node->left, ' * ', $node->right); + } + + protected function pExpr_BinaryOp_Div(BinaryOp\Div $node) { + return $this->pInfixOp('Expr_BinaryOp_Div', $node->left, ' / ', $node->right); + } + + protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node) { + return $this->pInfixOp('Expr_BinaryOp_Concat', $node->left, ' . ', $node->right); + } + + protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node) { + return $this->pInfixOp('Expr_BinaryOp_Mod', $node->left, ' % ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node) { + return $this->pInfixOp('Expr_BinaryOp_BooleanAnd', $node->left, ' && ', $node->right); + } + + protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node) { + return $this->pInfixOp('Expr_BinaryOp_BooleanOr', $node->left, ' || ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node) { + return $this->pInfixOp('Expr_BinaryOp_BitwiseAnd', $node->left, ' & ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node) { + return $this->pInfixOp('Expr_BinaryOp_BitwiseOr', $node->left, ' | ', $node->right); + } + + protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node) { + return $this->pInfixOp('Expr_BinaryOp_BitwiseXor', $node->left, ' ^ ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node) { + return $this->pInfixOp('Expr_BinaryOp_ShiftLeft', $node->left, ' << ', $node->right); + } + + protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node) { + return $this->pInfixOp('Expr_BinaryOp_ShiftRight', $node->left, ' >> ', $node->right); + } + + protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node) { + return $this->pInfixOp('Expr_BinaryOp_Pow', $node->left, ' ** ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node) { + return $this->pInfixOp('Expr_BinaryOp_LogicalAnd', $node->left, ' and ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node) { + return $this->pInfixOp('Expr_BinaryOp_LogicalOr', $node->left, ' or ', $node->right); + } + + protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node) { + return $this->pInfixOp('Expr_BinaryOp_LogicalXor', $node->left, ' xor ', $node->right); + } + + protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node) { + return $this->pInfixOp('Expr_BinaryOp_Equal', $node->left, ' == ', $node->right); + } + + protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node) { + return $this->pInfixOp('Expr_BinaryOp_NotEqual', $node->left, ' != ', $node->right); + } + + protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node) { + return $this->pInfixOp('Expr_BinaryOp_Identical', $node->left, ' === ', $node->right); + } + + protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node) { + return $this->pInfixOp('Expr_BinaryOp_NotIdentical', $node->left, ' !== ', $node->right); + } + + protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node) { + return $this->pInfixOp('Expr_BinaryOp_Spaceship', $node->left, ' <=> ', $node->right); + } + + protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node) { + return $this->pInfixOp('Expr_BinaryOp_Greater', $node->left, ' > ', $node->right); + } + + protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node) { + return $this->pInfixOp('Expr_BinaryOp_GreaterOrEqual', $node->left, ' >= ', $node->right); + } + + protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node) { + return $this->pInfixOp('Expr_BinaryOp_Smaller', $node->left, ' < ', $node->right); + } + + protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node) { + return $this->pInfixOp('Expr_BinaryOp_SmallerOrEqual', $node->left, ' <= ', $node->right); + } + + protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node) { + return $this->pInfixOp('Expr_BinaryOp_Coalesce', $node->left, ' ?? ', $node->right); + } + + protected function pExpr_Instanceof(Expr\Instanceof_ $node) { + return $this->pInfixOp('Expr_Instanceof', $node->expr, ' instanceof ', $node->class); + } + + // Unary expressions + + protected function pExpr_BooleanNot(Expr\BooleanNot $node) { + return $this->pPrefixOp('Expr_BooleanNot', '!', $node->expr); + } + + protected function pExpr_BitwiseNot(Expr\BitwiseNot $node) { + return $this->pPrefixOp('Expr_BitwiseNot', '~', $node->expr); + } + + protected function pExpr_UnaryMinus(Expr\UnaryMinus $node) { + if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) { + // Enforce -(-$expr) instead of --$expr + return '-(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp('Expr_UnaryMinus', '-', $node->expr); + } + + protected function pExpr_UnaryPlus(Expr\UnaryPlus $node) { + if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) { + // Enforce +(+$expr) instead of ++$expr + return '+(' . $this->p($node->expr) . ')'; + } + return $this->pPrefixOp('Expr_UnaryPlus', '+', $node->expr); + } + + protected function pExpr_PreInc(Expr\PreInc $node) { + return $this->pPrefixOp('Expr_PreInc', '++', $node->var); + } + + protected function pExpr_PreDec(Expr\PreDec $node) { + return $this->pPrefixOp('Expr_PreDec', '--', $node->var); + } + + protected function pExpr_PostInc(Expr\PostInc $node) { + return $this->pPostfixOp('Expr_PostInc', $node->var, '++'); + } + + protected function pExpr_PostDec(Expr\PostDec $node) { + return $this->pPostfixOp('Expr_PostDec', $node->var, '--'); + } + + protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node) { + return $this->pPrefixOp('Expr_ErrorSuppress', '@', $node->expr); + } + + protected function pExpr_YieldFrom(Expr\YieldFrom $node) { + return $this->pPrefixOp('Expr_YieldFrom', 'yield from ', $node->expr); + } + + protected function pExpr_Print(Expr\Print_ $node) { + return $this->pPrefixOp('Expr_Print', 'print ', $node->expr); + } + + // Casts + + protected function pExpr_Cast_Int(Cast\Int_ $node) { + return $this->pPrefixOp('Expr_Cast_Int', '(int) ', $node->expr); + } + + protected function pExpr_Cast_Double(Cast\Double $node) { + return $this->pPrefixOp('Expr_Cast_Double', '(double) ', $node->expr); + } + + protected function pExpr_Cast_String(Cast\String_ $node) { + return $this->pPrefixOp('Expr_Cast_String', '(string) ', $node->expr); + } + + protected function pExpr_Cast_Array(Cast\Array_ $node) { + return $this->pPrefixOp('Expr_Cast_Array', '(array) ', $node->expr); + } + + protected function pExpr_Cast_Object(Cast\Object_ $node) { + return $this->pPrefixOp('Expr_Cast_Object', '(object) ', $node->expr); + } + + protected function pExpr_Cast_Bool(Cast\Bool_ $node) { + return $this->pPrefixOp('Expr_Cast_Bool', '(bool) ', $node->expr); + } + + protected function pExpr_Cast_Unset(Cast\Unset_ $node) { + return $this->pPrefixOp('Expr_Cast_Unset', '(unset) ', $node->expr); + } + + // Function calls and similar constructs + + protected function pExpr_FuncCall(Expr\FuncCall $node) { + return $this->pCallLhs($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_MethodCall(Expr\MethodCall $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_StaticCall(Expr\StaticCall $node) { + return $this->pDereferenceLhs($node->class) . '::' + . ($node->name instanceof Expr + ? ($node->name instanceof Expr\Variable + ? $this->p($node->name) + : '{' . $this->p($node->name) . '}') + : $node->name) + . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Empty(Expr\Empty_ $node) { + return 'empty(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Isset(Expr\Isset_ $node) { + return 'isset(' . $this->pCommaSeparated($node->vars) . ')'; + } + + protected function pExpr_Eval(Expr\Eval_ $node) { + return 'eval(' . $this->p($node->expr) . ')'; + } + + protected function pExpr_Include(Expr\Include_ $node) { + static $map = array( + Expr\Include_::TYPE_INCLUDE => 'include', + Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', + Expr\Include_::TYPE_REQUIRE => 'require', + Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once', + ); + + return $map[$node->type] . ' ' . $this->p($node->expr); + } + + protected function pExpr_List(Expr\List_ $node) { + return 'list(' . $this->pCommaSeparated($node->items) . ')'; + } + + // Other + + protected function pExpr_Error(Expr\Error $node) { + throw new \LogicException('Cannot pretty-print AST with Error nodes'); + } + + protected function pExpr_Variable(Expr\Variable $node) { + if ($node->name instanceof Expr) { + return '${' . $this->p($node->name) . '}'; + } else { + return '$' . $node->name; + } + } + + protected function pExpr_Array(Expr\Array_ $node) { + $syntax = $node->getAttribute('kind', + $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG); + if ($syntax === Expr\Array_::KIND_SHORT) { + return '[' . $this->pMaybeMultiline($node->items, true) . ']'; + } else { + return 'array(' . $this->pMaybeMultiline($node->items, true) . ')'; + } + } + + protected function pExpr_ArrayItem(Expr\ArrayItem $node) { + return (null !== $node->key ? $this->p($node->key) . ' => ' : '') + . ($node->byRef ? '&' : '') . $this->p($node->value); + } + + protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node) { + return $this->pDereferenceLhs($node->var) + . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']'; + } + + protected function pExpr_ConstFetch(Expr\ConstFetch $node) { + return $this->p($node->name); + } + + protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node) { + return $this->p($node->class) . '::' + . (is_string($node->name) ? $node->name : $this->p($node->name)); + } + + protected function pExpr_PropertyFetch(Expr\PropertyFetch $node) { + return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name); + } + + protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node) { + return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name); + } + + protected function pExpr_ShellExec(Expr\ShellExec $node) { + return '`' . $this->pEncapsList($node->parts, '`') . '`'; + } + + protected function pExpr_Closure(Expr\Closure $node) { + return ($node->static ? 'static ' : '') + . 'function ' . ($node->byRef ? '&' : '') + . '(' . $this->pCommaSeparated($node->params) . ')' + . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')': '') + . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') + . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pExpr_ClosureUse(Expr\ClosureUse $node) { + return ($node->byRef ? '&' : '') . '$' . $node->var; + } + + protected function pExpr_New(Expr\New_ $node) { + if ($node->class instanceof Stmt\Class_) { + $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : ''; + return 'new ' . $this->pClassCommon($node->class, $args); + } + return 'new ' . $this->p($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')'; + } + + protected function pExpr_Clone(Expr\Clone_ $node) { + return 'clone ' . $this->p($node->expr); + } + + protected function pExpr_Ternary(Expr\Ternary $node) { + // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator. + // this is okay because the part between ? and : never needs parentheses. + return $this->pInfixOp('Expr_Ternary', + $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else + ); + } + + protected function pExpr_Exit(Expr\Exit_ $node) { + $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE); + return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') + . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : ''); + } + + protected function pExpr_Yield(Expr\Yield_ $node) { + if ($node->value === null) { + return 'yield'; + } else { + // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary + return '(yield ' + . ($node->key !== null ? $this->p($node->key) . ' => ' : '') + . $this->p($node->value) + . ')'; + } + } + + // Declarations + + protected function pStmt_Namespace(Stmt\Namespace_ $node) { + if ($this->canUseSemicolonNamespaces) { + return 'namespace ' . $this->p($node->name) . ';' . "\n" . $this->pStmts($node->stmts, false); + } else { + return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') + . ' {' . $this->pStmts($node->stmts) . "\n" . '}'; + } + } + + protected function pStmt_Use(Stmt\Use_ $node) { + return 'use ' . $this->pUseType($node->type) + . $this->pCommaSeparated($node->uses) . ';'; + } + + protected function pStmt_GroupUse(Stmt\GroupUse $node) { + return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) + . '\{' . $this->pCommaSeparated($node->uses) . '};'; + } + + protected function pStmt_UseUse(Stmt\UseUse $node) { + return $this->pUseType($node->type) . $this->p($node->name) + . ($node->name->getLast() !== $node->alias ? ' as ' . $node->alias : ''); + } + + protected function pUseType($type) { + return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' + : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : ''); + } + + protected function pStmt_Interface(Stmt\Interface_ $node) { + return 'interface ' . $node->name + . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') + . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Class(Stmt\Class_ $node) { + return $this->pClassCommon($node, ' ' . $node->name); + } + + protected function pStmt_Trait(Stmt\Trait_ $node) { + return 'trait ' . $node->name + . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_TraitUse(Stmt\TraitUse $node) { + return 'use ' . $this->pCommaSeparated($node->traits) + . (empty($node->adaptations) + ? ';' + : ' {' . $this->pStmts($node->adaptations) . "\n" . '}'); + } + + protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node) { + return $this->p($node->trait) . '::' . $node->method + . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';'; + } + + protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node) { + return (null !== $node->trait ? $this->p($node->trait) . '::' : '') + . $node->method . ' as' + . (null !== $node->newModifier ? ' ' . rtrim($this->pModifiers($node->newModifier), ' ') : '') + . (null !== $node->newName ? ' ' . $node->newName : '') + . ';'; + } + + protected function pStmt_Property(Stmt\Property $node) { + return (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . $this->pCommaSeparated($node->props) . ';'; + } + + protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node) { + return '$' . $node->name + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_ClassMethod(Stmt\ClassMethod $node) { + return $this->pModifiers($node->flags) + . 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') + . (null !== $node->stmts + ? "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}' + : ';'); + } + + protected function pStmt_ClassConst(Stmt\ClassConst $node) { + return $this->pModifiers($node->flags) + . 'const ' . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Function(Stmt\Function_ $node) { + return 'function ' . ($node->byRef ? '&' : '') . $node->name + . '(' . $this->pCommaSeparated($node->params) . ')' + . (null !== $node->returnType ? ' : ' . $this->pType($node->returnType) : '') + . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Const(Stmt\Const_ $node) { + return 'const ' . $this->pCommaSeparated($node->consts) . ';'; + } + + protected function pStmt_Declare(Stmt\Declare_ $node) { + return 'declare (' . $this->pCommaSeparated($node->declares) . ')' + . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . "\n" . '}' : ';'); + } + + protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node) { + return $node->key . '=' . $this->p($node->value); + } + + // Control flow + + protected function pStmt_If(Stmt\If_ $node) { + return 'if (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . "\n" . '}' + . $this->pImplode($node->elseifs) + . (null !== $node->else ? $this->p($node->else) : ''); + } + + protected function pStmt_ElseIf(Stmt\ElseIf_ $node) { + return ' elseif (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Else(Stmt\Else_ $node) { + return ' else {' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_For(Stmt\For_ $node) { + return 'for (' + . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') + . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') + . $this->pCommaSeparated($node->loop) + . ') {' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Foreach(Stmt\Foreach_ $node) { + return 'foreach (' . $this->p($node->expr) . ' as ' + . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') + . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' + . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_While(Stmt\While_ $node) { + return 'while (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Do(Stmt\Do_ $node) { + return 'do {' . $this->pStmts($node->stmts) . "\n" + . '} while (' . $this->p($node->cond) . ');'; + } + + protected function pStmt_Switch(Stmt\Switch_ $node) { + return 'switch (' . $this->p($node->cond) . ') {' + . $this->pStmts($node->cases) . "\n" . '}'; + } + + protected function pStmt_Case(Stmt\Case_ $node) { + return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' + . $this->pStmts($node->stmts); + } + + protected function pStmt_TryCatch(Stmt\TryCatch $node) { + return 'try {' . $this->pStmts($node->stmts) . "\n" . '}' + . $this->pImplode($node->catches) + . ($node->finally !== null ? $this->p($node->finally) : ''); + } + + protected function pStmt_Catch(Stmt\Catch_ $node) { + return ' catch (' . $this->pImplode($node->types, '|') . ' $' . $node->var . ') {' + . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Finally(Stmt\Finally_ $node) { + return ' finally {' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pStmt_Break(Stmt\Break_ $node) { + return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Continue(Stmt\Continue_ $node) { + return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';'; + } + + protected function pStmt_Return(Stmt\Return_ $node) { + return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';'; + } + + protected function pStmt_Throw(Stmt\Throw_ $node) { + return 'throw ' . $this->p($node->expr) . ';'; + } + + protected function pStmt_Label(Stmt\Label $node) { + return $node->name . ':'; + } + + protected function pStmt_Goto(Stmt\Goto_ $node) { + return 'goto ' . $node->name . ';'; + } + + // Other + + protected function pStmt_Echo(Stmt\Echo_ $node) { + return 'echo ' . $this->pCommaSeparated($node->exprs) . ';'; + } + + protected function pStmt_Static(Stmt\Static_ $node) { + return 'static ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_Global(Stmt\Global_ $node) { + return 'global ' . $this->pCommaSeparated($node->vars) . ';'; + } + + protected function pStmt_StaticVar(Stmt\StaticVar $node) { + return '$' . $node->name + . (null !== $node->default ? ' = ' . $this->p($node->default) : ''); + } + + protected function pStmt_Unset(Stmt\Unset_ $node) { + return 'unset(' . $this->pCommaSeparated($node->vars) . ');'; + } + + protected function pStmt_InlineHTML(Stmt\InlineHTML $node) { + $newline = $node->getAttribute('hasLeadingNewline', true) ? "\n" : ''; + return '?>' . $this->pNoIndent($newline . $node->value) . 'remaining; + } + + protected function pStmt_Nop(Stmt\Nop $node) { + return ''; + } + + // Helpers + + protected function pType($node) { + return is_string($node) ? $node : $this->p($node); + } + + protected function pClassCommon(Stmt\Class_ $node, $afterClassToken) { + return $this->pModifiers($node->flags) + . 'class' . $afterClassToken + . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') + . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') + . "\n" . '{' . $this->pStmts($node->stmts) . "\n" . '}'; + } + + protected function pObjectProperty($node) { + if ($node instanceof Expr) { + return '{' . $this->p($node) . '}'; + } else { + return $node; + } + } + + protected function pModifiers($modifiers) { + return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') + . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : ''); + } + + protected function pEncapsList(array $encapsList, $quote) { + $return = ''; + foreach ($encapsList as $element) { + if ($element instanceof Scalar\EncapsedStringPart) { + $return .= $this->escapeString($element->value, $quote); + } else { + $return .= '{' . $this->p($element) . '}'; + } + } + + return $return; + } + + protected function escapeString($string, $quote) { + if (null === $quote) { + // For doc strings, don't escape newlines + $escaped = addcslashes($string, "\t\f\v$\\"); + } else { + $escaped = addcslashes($string, "\n\r\t\f\v$" . $quote . "\\"); + } + + // Escape other control characters + return preg_replace_callback('/([\0-\10\16-\37])(?=([0-7]?))/', function ($matches) { + $oct = decoct(ord($matches[1])); + if ($matches[2] !== '') { + // If there is a trailing digit, use the full three character form + return '\\' . str_pad($oct, 3, '0', STR_PAD_LEFT); + } + return '\\' . $oct; + }, $escaped); + } + + protected function containsEndLabel($string, $label, $atStart = true, $atEnd = true) { + $start = $atStart ? '(?:^|[\r\n])' : '[\r\n]'; + $end = $atEnd ? '(?:$|[;\r\n])' : '[;\r\n]'; + return false !== strpos($string, $label) + && preg_match('/' . $start . $label . $end . '/', $string); + } + + protected function encapsedContainsEndLabel(array $parts, $label) { + foreach ($parts as $i => $part) { + $atStart = $i === 0; + $atEnd = $i === count($parts) - 1; + if ($part instanceof Scalar\EncapsedStringPart + && $this->containsEndLabel($part->value, $label, $atStart, $atEnd) + ) { + return true; + } + } + return false; + } + + protected function pDereferenceLhs(Node $node) { + if ($node instanceof Expr\Variable + || $node instanceof Name + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\PropertyFetch + || $node instanceof Expr\StaticPropertyFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_ + || $node instanceof Scalar\String_ + || $node instanceof Expr\ConstFetch + || $node instanceof Expr\ClassConstFetch + ) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + protected function pCallLhs(Node $node) { + if ($node instanceof Name + || $node instanceof Expr\Variable + || $node instanceof Expr\ArrayDimFetch + || $node instanceof Expr\FuncCall + || $node instanceof Expr\MethodCall + || $node instanceof Expr\StaticCall + || $node instanceof Expr\Array_ + ) { + return $this->p($node); + } else { + return '(' . $this->p($node) . ')'; + } + } + + private function hasNodeWithComments(array $nodes) { + foreach ($nodes as $node) { + if ($node && $node->getAttribute('comments')) { + return true; + } + } + return false; + } + + private function pMaybeMultiline(array $nodes, $trailingComma = false) { + if (!$this->hasNodeWithComments($nodes)) { + return $this->pCommaSeparated($nodes); + } else { + return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . "\n"; + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php new file mode 100644 index 0000000..24bae59 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php @@ -0,0 +1,348 @@ + array( 0, 1), + 'Expr_BitwiseNot' => array( 10, 1), + 'Expr_PreInc' => array( 10, 1), + 'Expr_PreDec' => array( 10, 1), + 'Expr_PostInc' => array( 10, -1), + 'Expr_PostDec' => array( 10, -1), + 'Expr_UnaryPlus' => array( 10, 1), + 'Expr_UnaryMinus' => array( 10, 1), + 'Expr_Cast_Int' => array( 10, 1), + 'Expr_Cast_Double' => array( 10, 1), + 'Expr_Cast_String' => array( 10, 1), + 'Expr_Cast_Array' => array( 10, 1), + 'Expr_Cast_Object' => array( 10, 1), + 'Expr_Cast_Bool' => array( 10, 1), + 'Expr_Cast_Unset' => array( 10, 1), + 'Expr_ErrorSuppress' => array( 10, 1), + 'Expr_Instanceof' => array( 20, 0), + 'Expr_BooleanNot' => array( 30, 1), + 'Expr_BinaryOp_Mul' => array( 40, -1), + 'Expr_BinaryOp_Div' => array( 40, -1), + 'Expr_BinaryOp_Mod' => array( 40, -1), + 'Expr_BinaryOp_Plus' => array( 50, -1), + 'Expr_BinaryOp_Minus' => array( 50, -1), + 'Expr_BinaryOp_Concat' => array( 50, -1), + 'Expr_BinaryOp_ShiftLeft' => array( 60, -1), + 'Expr_BinaryOp_ShiftRight' => array( 60, -1), + 'Expr_BinaryOp_Smaller' => array( 70, 0), + 'Expr_BinaryOp_SmallerOrEqual' => array( 70, 0), + 'Expr_BinaryOp_Greater' => array( 70, 0), + 'Expr_BinaryOp_GreaterOrEqual' => array( 70, 0), + 'Expr_BinaryOp_Equal' => array( 80, 0), + 'Expr_BinaryOp_NotEqual' => array( 80, 0), + 'Expr_BinaryOp_Identical' => array( 80, 0), + 'Expr_BinaryOp_NotIdentical' => array( 80, 0), + 'Expr_BinaryOp_Spaceship' => array( 80, 0), + 'Expr_BinaryOp_BitwiseAnd' => array( 90, -1), + 'Expr_BinaryOp_BitwiseXor' => array(100, -1), + 'Expr_BinaryOp_BitwiseOr' => array(110, -1), + 'Expr_BinaryOp_BooleanAnd' => array(120, -1), + 'Expr_BinaryOp_BooleanOr' => array(130, -1), + 'Expr_BinaryOp_Coalesce' => array(140, 1), + 'Expr_Ternary' => array(150, -1), + // parser uses %left for assignments, but they really behave as %right + 'Expr_Assign' => array(160, 1), + 'Expr_AssignRef' => array(160, 1), + 'Expr_AssignOp_Plus' => array(160, 1), + 'Expr_AssignOp_Minus' => array(160, 1), + 'Expr_AssignOp_Mul' => array(160, 1), + 'Expr_AssignOp_Div' => array(160, 1), + 'Expr_AssignOp_Concat' => array(160, 1), + 'Expr_AssignOp_Mod' => array(160, 1), + 'Expr_AssignOp_BitwiseAnd' => array(160, 1), + 'Expr_AssignOp_BitwiseOr' => array(160, 1), + 'Expr_AssignOp_BitwiseXor' => array(160, 1), + 'Expr_AssignOp_ShiftLeft' => array(160, 1), + 'Expr_AssignOp_ShiftRight' => array(160, 1), + 'Expr_AssignOp_Pow' => array(160, 1), + 'Expr_YieldFrom' => array(165, 1), + 'Expr_Print' => array(168, 1), + 'Expr_BinaryOp_LogicalAnd' => array(170, -1), + 'Expr_BinaryOp_LogicalXor' => array(180, -1), + 'Expr_BinaryOp_LogicalOr' => array(190, -1), + 'Expr_Include' => array(200, -1), + ); + + protected $noIndentToken; + protected $docStringEndToken; + protected $canUseSemicolonNamespaces; + protected $options; + + /** + * Creates a pretty printer instance using the given options. + * + * Supported options: + * * bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array + * syntax, if the node does not specify a format. + * + * @param array $options Dictionary of formatting options + */ + public function __construct(array $options = []) { + $this->noIndentToken = '_NO_INDENT_' . mt_rand(); + $this->docStringEndToken = '_DOC_STRING_END_' . mt_rand(); + + $defaultOptions = ['shortArraySyntax' => false]; + $this->options = $options + $defaultOptions; + } + + /** + * Pretty prints an array of statements. + * + * @param Node[] $stmts Array of statements + * + * @return string Pretty printed statements + */ + public function prettyPrint(array $stmts) { + $this->preprocessNodes($stmts); + + return ltrim($this->handleMagicTokens($this->pStmts($stmts, false))); + } + + /** + * Pretty prints an expression. + * + * @param Expr $node Expression node + * + * @return string Pretty printed node + */ + public function prettyPrintExpr(Expr $node) { + return $this->handleMagicTokens($this->p($node)); + } + + /** + * Pretty prints a file of statements (includes the opening prettyPrint($stmts); + + if ($stmts[0] instanceof Stmt\InlineHTML) { + $p = preg_replace('/^<\?php\s+\?>\n?/', '', $p); + } + if ($stmts[count($stmts) - 1] instanceof Stmt\InlineHTML) { + $p = preg_replace('/<\?php$/', '', rtrim($p)); + } + + return $p; + } + + /** + * Preprocesses the top-level nodes to initialize pretty printer state. + * + * @param Node[] $nodes Array of nodes + */ + protected function preprocessNodes(array $nodes) { + /* We can use semicolon-namespaces unless there is a global namespace declaration */ + $this->canUseSemicolonNamespaces = true; + foreach ($nodes as $node) { + if ($node instanceof Stmt\Namespace_ && null === $node->name) { + $this->canUseSemicolonNamespaces = false; + } + } + } + + protected function handleMagicTokens($str) { + // Drop no-indent tokens + $str = str_replace($this->noIndentToken, '', $str); + + // Replace doc-string-end tokens with nothing or a newline + $str = str_replace($this->docStringEndToken . ";\n", ";\n", $str); + $str = str_replace($this->docStringEndToken, "\n", $str); + + return $str; + } + + /** + * Pretty prints an array of nodes (statements) and indents them optionally. + * + * @param Node[] $nodes Array of nodes + * @param bool $indent Whether to indent the printed nodes + * + * @return string Pretty printed statements + */ + protected function pStmts(array $nodes, $indent = true) { + $result = ''; + foreach ($nodes as $node) { + $comments = $node->getAttribute('comments', array()); + if ($comments) { + $result .= "\n" . $this->pComments($comments); + if ($node instanceof Stmt\Nop) { + continue; + } + } + + $result .= "\n" . $this->p($node) . ($node instanceof Expr ? ';' : ''); + } + + if ($indent) { + return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n ", $result); + } else { + return $result; + } + } + + /** + * Pretty prints a node. + * + * @param Node $node Node to be pretty printed + * + * @return string Pretty printed node + */ + protected function p(Node $node) { + return $this->{'p' . $node->getType()}($node); + } + + protected function pInfixOp($type, Node $leftNode, $operatorString, Node $rightNode) { + list($precedence, $associativity) = $this->precedenceMap[$type]; + + return $this->pPrec($leftNode, $precedence, $associativity, -1) + . $operatorString + . $this->pPrec($rightNode, $precedence, $associativity, 1); + } + + protected function pPrefixOp($type, $operatorString, Node $node) { + list($precedence, $associativity) = $this->precedenceMap[$type]; + return $operatorString . $this->pPrec($node, $precedence, $associativity, 1); + } + + protected function pPostfixOp($type, Node $node, $operatorString) { + list($precedence, $associativity) = $this->precedenceMap[$type]; + return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString; + } + + /** + * Prints an expression node with the least amount of parentheses necessary to preserve the meaning. + * + * @param Node $node Node to pretty print + * @param int $parentPrecedence Precedence of the parent operator + * @param int $parentAssociativity Associativity of parent operator + * (-1 is left, 0 is nonassoc, 1 is right) + * @param int $childPosition Position of the node relative to the operator + * (-1 is left, 1 is right) + * + * @return string The pretty printed node + */ + protected function pPrec(Node $node, $parentPrecedence, $parentAssociativity, $childPosition) { + $type = $node->getType(); + if (isset($this->precedenceMap[$type])) { + $childPrecedence = $this->precedenceMap[$type][0]; + if ($childPrecedence > $parentPrecedence + || ($parentPrecedence == $childPrecedence && $parentAssociativity != $childPosition) + ) { + return '(' . $this->p($node) . ')'; + } + } + + return $this->p($node); + } + + /** + * Pretty prints an array of nodes and implodes the printed values. + * + * @param Node[] $nodes Array of Nodes to be printed + * @param string $glue Character to implode with + * + * @return string Imploded pretty printed nodes + */ + protected function pImplode(array $nodes, $glue = '') { + $pNodes = array(); + foreach ($nodes as $node) { + if (null === $node) { + $pNodes[] = ''; + } else { + $pNodes[] = $this->p($node); + } + } + + return implode($glue, $pNodes); + } + + /** + * Pretty prints an array of nodes and implodes the printed values with commas. + * + * @param Node[] $nodes Array of Nodes to be printed + * + * @return string Comma separated pretty printed nodes + */ + protected function pCommaSeparated(array $nodes) { + return $this->pImplode($nodes, ', '); + } + + /** + * Pretty prints a comma-separated list of nodes in multiline style, including comments. + * + * The result includes a leading newline and one level of indentation (same as pStmts). + * + * @param Node[] $nodes Array of Nodes to be printed + * @param bool $trailingComma Whether to use a trailing comma + * + * @return string Comma separated pretty printed nodes in multiline style + */ + protected function pCommaSeparatedMultiline(array $nodes, $trailingComma) { + $result = ''; + $lastIdx = count($nodes) - 1; + foreach ($nodes as $idx => $node) { + if ($node !== null) { + $comments = $node->getAttribute('comments', array()); + if ($comments) { + $result .= "\n" . $this->pComments($comments); + } + + $result .= "\n" . $this->p($node); + } else { + $result .= "\n"; + } + if ($trailingComma || $idx !== $lastIdx) { + $result .= ','; + } + } + + return preg_replace('~\n(?!$|' . $this->noIndentToken . ')~', "\n ", $result); + } + + /** + * Signals the pretty printer that a string shall not be indented. + * + * @param string $string Not to be indented string + * + * @return string String marked with $this->noIndentToken's. + */ + protected function pNoIndent($string) { + return str_replace("\n", "\n" . $this->noIndentToken, $string); + } + + /** + * Prints reformatted text of the passed comments. + * + * @param Comment[] $comments List of comments + * + * @return string Reformatted text of comments + */ + protected function pComments(array $comments) { + $formattedComments = []; + + foreach ($comments as $comment) { + $formattedComments[] = $comment->getReformattedText(); + } + + return implode("\n", $formattedComments); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Serializer.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Serializer.php new file mode 100644 index 0000000..1dd7906 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Serializer.php @@ -0,0 +1,18 @@ +writer = new XMLWriter; + $this->writer->openMemory(); + $this->writer->setIndent(true); + } + + public function serialize(array $nodes) { + $this->writer->flush(); + $this->writer->startDocument('1.0', 'UTF-8'); + + $this->writer->startElement('AST'); + $this->writer->writeAttribute('xmlns:node', 'http://nikic.github.com/PHPParser/XML/node'); + $this->writer->writeAttribute('xmlns:subNode', 'http://nikic.github.com/PHPParser/XML/subNode'); + $this->writer->writeAttribute('xmlns:attribute', 'http://nikic.github.com/PHPParser/XML/attribute'); + $this->writer->writeAttribute('xmlns:scalar', 'http://nikic.github.com/PHPParser/XML/scalar'); + + $this->_serialize($nodes); + + $this->writer->endElement(); + + return $this->writer->outputMemory(); + } + + protected function _serialize($node) { + if ($node instanceof Node) { + $this->writer->startElement('node:' . $node->getType()); + + foreach ($node->getAttributes() as $name => $value) { + $this->writer->startElement('attribute:' . $name); + $this->_serialize($value); + $this->writer->endElement(); + } + + foreach ($node as $name => $subNode) { + $this->writer->startElement('subNode:' . $name); + $this->_serialize($subNode); + $this->writer->endElement(); + } + + $this->writer->endElement(); + } elseif ($node instanceof Comment) { + $this->writer->startElement('comment'); + $this->writer->writeAttribute('isDocComment', $node instanceof Comment\Doc ? 'true' : 'false'); + $this->writer->writeAttribute('line', (string) $node->getLine()); + $this->writer->text($node->getText()); + $this->writer->endElement(); + } elseif (is_array($node)) { + $this->writer->startElement('scalar:array'); + foreach ($node as $subNode) { + $this->_serialize($subNode); + } + $this->writer->endElement(); + } elseif (is_string($node)) { + $this->writer->writeElement('scalar:string', $node); + } elseif (is_int($node)) { + $this->writer->writeElement('scalar:int', (string) $node); + } elseif (is_float($node)) { + // TODO Higher precision conversion? + $this->writer->writeElement('scalar:float', (string) $node); + } elseif (true === $node) { + $this->writer->writeElement('scalar:true'); + } elseif (false === $node) { + $this->writer->writeElement('scalar:false'); + } elseif (null === $node) { + $this->writer->writeElement('scalar:null'); + } else { + throw new \InvalidArgumentException('Unexpected node type'); + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Unserializer.php b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Unserializer.php new file mode 100644 index 0000000..9c221a1 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/PhpParser/Unserializer.php @@ -0,0 +1,18 @@ +reader = new XMLReader; + } + + public function unserialize($string) { + $this->reader->XML($string); + + $this->reader->read(); + if ('AST' !== $this->reader->name) { + throw new DomainException('AST root element not found'); + } + + return $this->read($this->reader->depth); + } + + protected function read($depthLimit, $throw = true, &$nodeFound = null) { + $nodeFound = true; + while ($this->reader->read() && $depthLimit < $this->reader->depth) { + if (XMLReader::ELEMENT !== $this->reader->nodeType) { + continue; + } + + if ('node' === $this->reader->prefix) { + return $this->readNode(); + } elseif ('scalar' === $this->reader->prefix) { + return $this->readScalar(); + } elseif ('comment' === $this->reader->name) { + return $this->readComment(); + } else { + throw new DomainException(sprintf('Unexpected node of type "%s"', $this->reader->name)); + } + } + + $nodeFound = false; + if ($throw) { + throw new DomainException('Expected node or scalar'); + } + } + + protected function readNode() { + $className = $this->getClassNameFromType($this->reader->localName); + + // create the node without calling it's constructor + $node = unserialize( + sprintf( + "O:%d:\"%s\":1:{s:13:\"\0*\0attributes\";a:0:{}}", + strlen($className), $className + ) + ); + + $depthLimit = $this->reader->depth; + while ($this->reader->read() && $depthLimit < $this->reader->depth) { + if (XMLReader::ELEMENT !== $this->reader->nodeType) { + continue; + } + + $type = $this->reader->prefix; + if ('subNode' !== $type && 'attribute' !== $type) { + throw new DomainException( + sprintf('Expected sub node or attribute, got node of type "%s"', $this->reader->name) + ); + } + + $name = $this->reader->localName; + $value = $this->read($this->reader->depth); + + if ('subNode' === $type) { + $node->$name = $value; + } else { + $node->setAttribute($name, $value); + } + } + + return $node; + } + + protected function readScalar() { + switch ($name = $this->reader->localName) { + case 'array': + $depth = $this->reader->depth; + $array = array(); + while (true) { + $node = $this->read($depth, false, $nodeFound); + if (!$nodeFound) { + break; + } + $array[] = $node; + } + return $array; + case 'string': + return $this->reader->readString(); + case 'int': + return $this->parseInt($this->reader->readString()); + case 'float': + $text = $this->reader->readString(); + if (false === $float = filter_var($text, FILTER_VALIDATE_FLOAT)) { + throw new DomainException(sprintf('"%s" is not a valid float', $text)); + } + return $float; + case 'true': + case 'false': + case 'null': + if (!$this->reader->isEmptyElement) { + throw new DomainException(sprintf('"%s" scalar must be empty', $name)); + } + return constant($name); + default: + throw new DomainException(sprintf('Unknown scalar type "%s"', $name)); + } + } + + private function parseInt($text) { + if (false === $int = filter_var($text, FILTER_VALIDATE_INT)) { + throw new DomainException(sprintf('"%s" is not a valid integer', $text)); + } + return $int; + } + + protected function readComment() { + $className = $this->reader->getAttribute('isDocComment') === 'true' + ? 'PhpParser\Comment\Doc' + : 'PhpParser\Comment' + ; + return new $className( + $this->reader->readString(), + $this->parseInt($this->reader->getAttribute('line')) + ); + } + + protected function getClassNameFromType($type) { + $className = 'PhpParser\\Node\\' . strtr($type, '_', '\\'); + if (!class_exists($className)) { + $className .= '_'; + } + if (!class_exists($className)) { + throw new DomainException(sprintf('Unknown node type "%s"', $type)); + } + return $className; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/lib/bootstrap.php b/www/multitube/vendor/nikic/php-parser/lib/bootstrap.php new file mode 100644 index 0000000..b0f5178 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/lib/bootstrap.php @@ -0,0 +1,6 @@ + + + + + + ./test/ + + + + + + ./lib/PhpParser/ + + + diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/AutoloaderTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/AutoloaderTest.php new file mode 100644 index 0000000..8eeded8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/AutoloaderTest.php @@ -0,0 +1,15 @@ +assertTrue(class_exists('PhpParser\NodeVisitorAbstract')); + $this->assertFalse(class_exists('PHPParser_NodeVisitor_NameResolver')); + + $this->assertFalse(class_exists('PhpParser\FooBar')); + $this->assertFalse(class_exists('PHPParser_FooBar')); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ClassTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ClassTest.php new file mode 100644 index 0000000..0f74182 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ClassTest.php @@ -0,0 +1,161 @@ +createClassBuilder('SomeLogger') + ->extend('BaseLogger') + ->implement('Namespaced\Logger', new Name('SomeInterface')) + ->implement('\Fully\Qualified', 'namespace\NamespaceRelative') + ->getNode() + ; + + $this->assertEquals( + new Stmt\Class_('SomeLogger', array( + 'extends' => new Name('BaseLogger'), + 'implements' => array( + new Name('Namespaced\Logger'), + new Name('SomeInterface'), + new Name\FullyQualified('Fully\Qualified'), + new Name\Relative('NamespaceRelative'), + ), + )), + $node + ); + } + + public function testAbstract() { + $node = $this->createClassBuilder('Test') + ->makeAbstract() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Class_('Test', array( + 'flags' => Stmt\Class_::MODIFIER_ABSTRACT + )), + $node + ); + } + + public function testFinal() { + $node = $this->createClassBuilder('Test') + ->makeFinal() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Class_('Test', array( + 'flags' => Stmt\Class_::MODIFIER_FINAL + )), + $node + ); + } + + public function testStatementOrder() { + $method = new Stmt\ClassMethod('testMethod'); + $property = new Stmt\Property( + Stmt\Class_::MODIFIER_PUBLIC, + array(new Stmt\PropertyProperty('testProperty')) + ); + $const = new Stmt\ClassConst(array( + new Node\Const_('TEST_CONST', new Node\Scalar\String_('ABC')) + )); + $use = new Stmt\TraitUse(array(new Name('SomeTrait'))); + + $node = $this->createClassBuilder('Test') + ->addStmt($method) + ->addStmt($property) + ->addStmts(array($const, $use)) + ->getNode() + ; + + $this->assertEquals( + new Stmt\Class_('Test', array( + 'stmts' => array($use, $const, $property, $method) + )), + $node + ); + } + + public function testDocComment() { + $docComment = <<<'DOC' +/** + * Test + */ +DOC; + $class = $this->createClassBuilder('Test') + ->setDocComment($docComment) + ->getNode(); + + $this->assertEquals( + new Stmt\Class_('Test', array(), array( + 'comments' => array( + new Comment\Doc($docComment) + ) + )), + $class + ); + + $class = $this->createClassBuilder('Test') + ->setDocComment(new Comment\Doc($docComment)) + ->getNode(); + + $this->assertEquals( + new Stmt\Class_('Test', array(), array( + 'comments' => array( + new Comment\Doc($docComment) + ) + )), + $class + ); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Unexpected node of type "Stmt_Echo" + */ + public function testInvalidStmtError() { + $this->createClassBuilder('Test') + ->addStmt(new Stmt\Echo_(array())) + ; + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Doc comment must be a string or an instance of PhpParser\Comment\Doc + */ + public function testInvalidDocComment() { + $this->createClassBuilder('Test') + ->setDocComment(new Comment('Test')); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Name cannot be empty + */ + public function testEmptyName() { + $this->createClassBuilder('Test') + ->extend(''); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Name must be a string or an instance of PhpParser\Node\Name + */ + public function testInvalidName() { + $this->createClassBuilder('Test') + ->extend(array('Foo')); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/FunctionTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/FunctionTest.php new file mode 100644 index 0000000..f6a9381 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/FunctionTest.php @@ -0,0 +1,106 @@ +createFunctionBuilder('test') + ->makeReturnByRef() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Function_('test', array( + 'byRef' => true + )), + $node + ); + } + + public function testParams() { + $param1 = new Node\Param('test1'); + $param2 = new Node\Param('test2'); + $param3 = new Node\Param('test3'); + + $node = $this->createFunctionBuilder('test') + ->addParam($param1) + ->addParams(array($param2, $param3)) + ->getNode() + ; + + $this->assertEquals( + new Stmt\Function_('test', array( + 'params' => array($param1, $param2, $param3) + )), + $node + ); + } + + public function testStmts() { + $stmt1 = new Print_(new String_('test1')); + $stmt2 = new Print_(new String_('test2')); + $stmt3 = new Print_(new String_('test3')); + + $node = $this->createFunctionBuilder('test') + ->addStmt($stmt1) + ->addStmts(array($stmt2, $stmt3)) + ->getNode() + ; + + $this->assertEquals( + new Stmt\Function_('test', array( + 'stmts' => array($stmt1, $stmt2, $stmt3) + )), + $node + ); + } + + public function testDocComment() { + $node = $this->createFunctionBuilder('test') + ->setDocComment('/** Test */') + ->getNode(); + + $this->assertEquals(new Stmt\Function_('test', array(), array( + 'comments' => array(new Comment\Doc('/** Test */')) + )), $node); + } + + public function testReturnType() { + $node = $this->createFunctionBuilder('test') + ->setReturnType('void') + ->getNode(); + + $this->assertEquals(new Stmt\Function_('test', array( + 'returnType' => 'void' + ), array()), $node); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage void type cannot be nullable + */ + public function testInvalidNullableVoidType() { + $this->createFunctionBuilder('test')->setReturnType('?void'); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Expected parameter node, got "Name" + */ + public function testInvalidParamError() { + $this->createFunctionBuilder('test') + ->addParam(new Node\Name('foo')) + ; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/InterfaceTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/InterfaceTest.php new file mode 100644 index 0000000..72c5866 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/InterfaceTest.php @@ -0,0 +1,105 @@ +builder = new Interface_('Contract'); + } + + private function dump($node) { + $pp = new \PhpParser\PrettyPrinter\Standard; + return $pp->prettyPrint(array($node)); + } + + public function testEmpty() { + $contract = $this->builder->getNode(); + $this->assertInstanceOf('PhpParser\Node\Stmt\Interface_', $contract); + $this->assertSame('Contract', $contract->name); + } + + public function testExtending() { + $contract = $this->builder->extend('Space\Root1', 'Root2')->getNode(); + $this->assertEquals( + new Stmt\Interface_('Contract', array( + 'extends' => array( + new Node\Name('Space\Root1'), + new Node\Name('Root2') + ), + )), $contract + ); + } + + public function testAddMethod() { + $method = new Stmt\ClassMethod('doSomething'); + $contract = $this->builder->addStmt($method)->getNode(); + $this->assertSame(array($method), $contract->stmts); + } + + public function testAddConst() { + $const = new Stmt\ClassConst(array( + new Node\Const_('SPEED_OF_LIGHT', new DNumber(299792458.0)) + )); + $contract = $this->builder->addStmt($const)->getNode(); + $this->assertSame(299792458.0, $contract->stmts[0]->consts[0]->value->value); + } + + public function testOrder() { + $const = new Stmt\ClassConst(array( + new Node\Const_('SPEED_OF_LIGHT', new DNumber(299792458)) + )); + $method = new Stmt\ClassMethod('doSomething'); + $contract = $this->builder + ->addStmt($method) + ->addStmt($const) + ->getNode() + ; + + $this->assertInstanceOf('PhpParser\Node\Stmt\ClassConst', $contract->stmts[0]); + $this->assertInstanceOf('PhpParser\Node\Stmt\ClassMethod', $contract->stmts[1]); + } + + public function testDocComment() { + $node = $this->builder + ->setDocComment('/** Test */') + ->getNode(); + + $this->assertEquals(new Stmt\Interface_('Contract', array(), array( + 'comments' => array(new Comment\Doc('/** Test */')) + )), $node); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Unexpected node of type "Stmt_PropertyProperty" + */ + public function testInvalidStmtError() { + $this->builder->addStmt(new Stmt\PropertyProperty('invalid')); + } + + public function testFullFunctional() { + $const = new Stmt\ClassConst(array( + new Node\Const_('SPEED_OF_LIGHT', new DNumber(299792458)) + )); + $method = new Stmt\ClassMethod('doSomething'); + $contract = $this->builder + ->addStmt($method) + ->addStmt($const) + ->getNode() + ; + + eval($this->dump($contract)); + + $this->assertTrue(interface_exists('Contract', false)); + } +} + diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/MethodTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/MethodTest.php new file mode 100644 index 0000000..21c5617 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/MethodTest.php @@ -0,0 +1,163 @@ +createMethodBuilder('test') + ->makePublic() + ->makeAbstract() + ->makeStatic() + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'flags' => Stmt\Class_::MODIFIER_PUBLIC + | Stmt\Class_::MODIFIER_ABSTRACT + | Stmt\Class_::MODIFIER_STATIC, + 'stmts' => null, + )), + $node + ); + + $node = $this->createMethodBuilder('test') + ->makeProtected() + ->makeFinal() + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'flags' => Stmt\Class_::MODIFIER_PROTECTED + | Stmt\Class_::MODIFIER_FINAL + )), + $node + ); + + $node = $this->createMethodBuilder('test') + ->makePrivate() + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'type' => Stmt\Class_::MODIFIER_PRIVATE + )), + $node + ); + } + + public function testReturnByRef() { + $node = $this->createMethodBuilder('test') + ->makeReturnByRef() + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'byRef' => true + )), + $node + ); + } + + public function testParams() { + $param1 = new Node\Param('test1'); + $param2 = new Node\Param('test2'); + $param3 = new Node\Param('test3'); + + $node = $this->createMethodBuilder('test') + ->addParam($param1) + ->addParams(array($param2, $param3)) + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'params' => array($param1, $param2, $param3) + )), + $node + ); + } + + public function testStmts() { + $stmt1 = new Print_(new String_('test1')); + $stmt2 = new Print_(new String_('test2')); + $stmt3 = new Print_(new String_('test3')); + + $node = $this->createMethodBuilder('test') + ->addStmt($stmt1) + ->addStmts(array($stmt2, $stmt3)) + ->getNode() + ; + + $this->assertEquals( + new Stmt\ClassMethod('test', array( + 'stmts' => array($stmt1, $stmt2, $stmt3) + )), + $node + ); + } + public function testDocComment() { + $node = $this->createMethodBuilder('test') + ->setDocComment('/** Test */') + ->getNode(); + + $this->assertEquals(new Stmt\ClassMethod('test', array(), array( + 'comments' => array(new Comment\Doc('/** Test */')) + )), $node); + } + + public function testReturnType() { + $node = $this->createMethodBuilder('test') + ->setReturnType('bool') + ->getNode(); + $this->assertEquals(new Stmt\ClassMethod('test', array( + 'returnType' => 'bool' + ), array()), $node); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot add statements to an abstract method + */ + public function testAddStmtToAbstractMethodError() { + $this->createMethodBuilder('test') + ->makeAbstract() + ->addStmt(new Print_(new String_('test'))) + ; + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot make method with statements abstract + */ + public function testMakeMethodWithStmtsAbstractError() { + $this->createMethodBuilder('test') + ->addStmt(new Print_(new String_('test'))) + ->makeAbstract() + ; + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Expected parameter node, got "Name" + */ + public function testInvalidParamError() { + $this->createMethodBuilder('test') + ->addParam(new Node\Name('foo')) + ; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/NamespaceTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/NamespaceTest.php new file mode 100644 index 0000000..88131fc --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/NamespaceTest.php @@ -0,0 +1,46 @@ + array($docComment)) + ); + + $node = $this->createNamespaceBuilder('Name\Space') + ->addStmt($stmt1) + ->addStmts(array($stmt2, $stmt3)) + ->setDocComment($docComment) + ->getNode() + ; + $this->assertEquals($expected, $node); + + $node = $this->createNamespaceBuilder(new Node\Name(array('Name', 'Space'))) + ->setDocComment($docComment) + ->addStmts(array($stmt1, $stmt2)) + ->addStmt($stmt3) + ->getNode() + ; + $this->assertEquals($expected, $node); + + $node = $this->createNamespaceBuilder(null)->getNode(); + $this->assertNull($node->name); + $this->assertEmpty($node->stmts); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ParamTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ParamTest.php new file mode 100644 index 0000000..e67ae99 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/ParamTest.php @@ -0,0 +1,171 @@ +createParamBuilder('test') + ->setDefault($value) + ->getNode() + ; + + $this->assertEquals($expectedValueNode, $node->default); + } + + public function provideTestDefaultValues() { + return array( + array( + null, + new Expr\ConstFetch(new Node\Name('null')) + ), + array( + true, + new Expr\ConstFetch(new Node\Name('true')) + ), + array( + false, + new Expr\ConstFetch(new Node\Name('false')) + ), + array( + 31415, + new Scalar\LNumber(31415) + ), + array( + 3.1415, + new Scalar\DNumber(3.1415) + ), + array( + 'Hallo World', + new Scalar\String_('Hallo World') + ), + array( + array(1, 2, 3), + new Expr\Array_(array( + new Expr\ArrayItem(new Scalar\LNumber(1)), + new Expr\ArrayItem(new Scalar\LNumber(2)), + new Expr\ArrayItem(new Scalar\LNumber(3)), + )) + ), + array( + array('foo' => 'bar', 'bar' => 'foo'), + new Expr\Array_(array( + new Expr\ArrayItem( + new Scalar\String_('bar'), + new Scalar\String_('foo') + ), + new Expr\ArrayItem( + new Scalar\String_('foo'), + new Scalar\String_('bar') + ), + )) + ), + array( + new Scalar\MagicConst\Dir, + new Scalar\MagicConst\Dir + ) + ); + } + + /** + * @dataProvider provideTestTypeHints + */ + public function testTypeHints($typeHint, $expectedType) { + $node = $this->createParamBuilder('test') + ->setTypeHint($typeHint) + ->getNode() + ; + $type = $node->type; + + /* Manually implement comparison to avoid __toString stupidity */ + if ($expectedType instanceof Node\NullableType) { + $this->assertInstanceOf(get_class($expectedType), $type); + $expectedType = $expectedType->type; + $type = $type->type; + } + + if ($expectedType instanceof Node\Name) { + $this->assertInstanceOf(get_class($expectedType), $type); + $this->assertEquals($expectedType, $type); + } else { + $this->assertSame($expectedType, $type); + } + } + + public function provideTestTypeHints() { + return array( + array('array', 'array'), + array('callable', 'callable'), + array('bool', 'bool'), + array('int', 'int'), + array('float', 'float'), + array('string', 'string'), + array('iterable', 'iterable'), + array('object', 'object'), + array('Array', 'array'), + array('CALLABLE', 'callable'), + array('Some\Class', new Node\Name('Some\Class')), + array('\Foo', new Node\Name\FullyQualified('Foo')), + array('self', new Node\Name('self')), + array('?array', new Node\NullableType('array')), + array('?Some\Class', new Node\NullableType(new Node\Name('Some\Class'))), + array(new Node\Name('Some\Class'), new Node\Name('Some\Class')), + array(new Node\NullableType('int'), new Node\NullableType('int')), + array( + new Node\NullableType(new Node\Name('Some\Class')), + new Node\NullableType(new Node\Name('Some\Class')) + ), + ); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Parameter type cannot be void + */ + public function testVoidTypeError() { + $this->createParamBuilder('test')->setTypeHint('void'); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Type must be a string, or an instance of Name or NullableType + */ + public function testInvalidTypeError() { + $this->createParamBuilder('test')->setTypeHint(new \stdClass); + } + + public function testByRef() { + $node = $this->createParamBuilder('test') + ->makeByRef() + ->getNode() + ; + + $this->assertEquals( + new Node\Param('test', null, null, true), + $node + ); + } + + public function testVariadic() { + $node = $this->createParamBuilder('test') + ->makeVariadic() + ->getNode() + ; + + $this->assertEquals( + new Node\Param('test', null, null, false, true), + $node + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/PropertyTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/PropertyTest.php new file mode 100644 index 0000000..de8f4ce --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/PropertyTest.php @@ -0,0 +1,147 @@ +createPropertyBuilder('test') + ->makePrivate() + ->makeStatic() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Property( + Stmt\Class_::MODIFIER_PRIVATE + | Stmt\Class_::MODIFIER_STATIC, + array( + new Stmt\PropertyProperty('test') + ) + ), + $node + ); + + $node = $this->createPropertyBuilder('test') + ->makeProtected() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Property( + Stmt\Class_::MODIFIER_PROTECTED, + array( + new Stmt\PropertyProperty('test') + ) + ), + $node + ); + + $node = $this->createPropertyBuilder('test') + ->makePublic() + ->getNode() + ; + + $this->assertEquals( + new Stmt\Property( + Stmt\Class_::MODIFIER_PUBLIC, + array( + new Stmt\PropertyProperty('test') + ) + ), + $node + ); + } + + public function testDocComment() { + $node = $this->createPropertyBuilder('test') + ->setDocComment('/** Test */') + ->getNode(); + + $this->assertEquals(new Stmt\Property( + Stmt\Class_::MODIFIER_PUBLIC, + array( + new Stmt\PropertyProperty('test') + ), + array( + 'comments' => array(new Comment\Doc('/** Test */')) + ) + ), $node); + } + + /** + * @dataProvider provideTestDefaultValues + */ + public function testDefaultValues($value, $expectedValueNode) { + $node = $this->createPropertyBuilder('test') + ->setDefault($value) + ->getNode() + ; + + $this->assertEquals($expectedValueNode, $node->props[0]->default); + } + + public function provideTestDefaultValues() { + return array( + array( + null, + new Expr\ConstFetch(new Name('null')) + ), + array( + true, + new Expr\ConstFetch(new Name('true')) + ), + array( + false, + new Expr\ConstFetch(new Name('false')) + ), + array( + 31415, + new Scalar\LNumber(31415) + ), + array( + 3.1415, + new Scalar\DNumber(3.1415) + ), + array( + 'Hallo World', + new Scalar\String_('Hallo World') + ), + array( + array(1, 2, 3), + new Expr\Array_(array( + new Expr\ArrayItem(new Scalar\LNumber(1)), + new Expr\ArrayItem(new Scalar\LNumber(2)), + new Expr\ArrayItem(new Scalar\LNumber(3)), + )) + ), + array( + array('foo' => 'bar', 'bar' => 'foo'), + new Expr\Array_(array( + new Expr\ArrayItem( + new Scalar\String_('bar'), + new Scalar\String_('foo') + ), + new Expr\ArrayItem( + new Scalar\String_('foo'), + new Scalar\String_('bar') + ), + )) + ), + array( + new Scalar\MagicConst\Dir, + new Scalar\MagicConst\Dir + ) + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/TraitTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/TraitTest.php new file mode 100644 index 0000000..874bc4d --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/TraitTest.php @@ -0,0 +1,48 @@ +createTraitBuilder('TestTrait') + ->setDocComment('/** Nice trait */') + ->addStmt($method1) + ->addStmts([$method2, $method3]) + ->addStmt($prop) + ->addStmt($use) + ->getNode(); + $this->assertEquals(new Stmt\Trait_('TestTrait', [ + 'stmts' => [$use, $prop, $method1, $method2, $method3] + ], [ + 'comments' => [ + new Comment\Doc('/** Nice trait */') + ] + ]), $trait); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Unexpected node of type "Stmt_Echo" + */ + public function testInvalidStmtError() { + $this->createTraitBuilder('Test') + ->addStmt(new Stmt\Echo_(array())) + ; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/UseTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/UseTest.php new file mode 100644 index 0000000..adaeb3a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Builder/UseTest.php @@ -0,0 +1,35 @@ +createUseBuilder('Foo\Bar')->getNode(); + $this->assertEquals(new Stmt\Use_(array( + new Stmt\UseUse(new Name('Foo\Bar'), 'Bar') + )), $node); + + $node = $this->createUseBuilder(new Name('Foo\Bar'))->as('XYZ')->getNode(); + $this->assertEquals(new Stmt\Use_(array( + new Stmt\UseUse(new Name('Foo\Bar'), 'XYZ') + )), $node); + + $node = $this->createUseBuilder('foo\bar', Stmt\Use_::TYPE_FUNCTION)->as('foo')->getNode(); + $this->assertEquals(new Stmt\Use_(array( + new Stmt\UseUse(new Name('foo\bar'), 'foo') + ), Stmt\Use_::TYPE_FUNCTION), $node); + } + + public function testNonExistingMethod() { + $this->setExpectedException('LogicException', 'Method "foo" does not exist'); + $builder = $this->createUseBuilder('Test'); + $builder->foo(); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/BuilderFactoryTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/BuilderFactoryTest.php new file mode 100644 index 0000000..1c3ef18 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/BuilderFactoryTest.php @@ -0,0 +1,108 @@ +assertInstanceOf($className, $factory->$methodName('test')); + } + + public function provideTestFactory() { + return array( + array('namespace', 'PhpParser\Builder\Namespace_'), + array('class', 'PhpParser\Builder\Class_'), + array('interface', 'PhpParser\Builder\Interface_'), + array('trait', 'PhpParser\Builder\Trait_'), + array('method', 'PhpParser\Builder\Method'), + array('function', 'PhpParser\Builder\Function_'), + array('property', 'PhpParser\Builder\Property'), + array('param', 'PhpParser\Builder\Param'), + array('use', 'PhpParser\Builder\Use_'), + ); + } + + public function testNonExistingMethod() { + $this->setExpectedException('LogicException', 'Method "foo" does not exist'); + $factory = new BuilderFactory(); + $factory->foo(); + } + + public function testIntegration() { + $factory = new BuilderFactory; + $node = $factory->namespace('Name\Space') + ->addStmt($factory->use('Foo\Bar\SomeOtherClass')) + ->addStmt($factory->use('Foo\Bar')->as('A')) + ->addStmt($factory + ->class('SomeClass') + ->extend('SomeOtherClass') + ->implement('A\Few', '\Interfaces') + ->makeAbstract() + + ->addStmt($factory->method('firstMethod')) + + ->addStmt($factory->method('someMethod') + ->makePublic() + ->makeAbstract() + ->addParam($factory->param('someParam')->setTypeHint('SomeClass')) + ->setDocComment('/** + * This method does something. + * + * @param SomeClass And takes a parameter + */')) + + ->addStmt($factory->method('anotherMethod') + ->makeProtected() + ->addParam($factory->param('someParam')->setDefault('test')) + ->addStmt(new Expr\Print_(new Expr\Variable('someParam')))) + + ->addStmt($factory->property('someProperty')->makeProtected()) + ->addStmt($factory->property('anotherProperty') + ->makePrivate() + ->setDefault(array(1, 2, 3)))) + ->getNode() + ; + + $expected = <<<'EOC' +prettyPrintFile($stmts); + + $this->assertEquals( + str_replace("\r\n", "\n", $expected), + str_replace("\r\n", "\n", $generated) + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeParsingTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeParsingTest.php new file mode 100644 index 0000000..1a4a9ad --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeParsingTest.php @@ -0,0 +1,70 @@ + array( + 'startLine', 'endLine', 'startFilePos', 'endFilePos', 'comments' + ))); + $parser5 = new Parser\Php5($lexer); + $parser7 = new Parser\Php7($lexer); + + $dumpPositions = isset($modes['positions']); + $output5 = $this->getParseOutput($parser5, $code, $dumpPositions); + $output7 = $this->getParseOutput($parser7, $code, $dumpPositions); + + if (isset($modes['php5'])) { + $this->assertSame($expected, $output5, $name); + $this->assertNotSame($expected, $output7, $name); + } else if (isset($modes['php7'])) { + $this->assertNotSame($expected, $output5, $name); + $this->assertSame($expected, $output7, $name); + } else { + $this->assertSame($expected, $output5, $name); + $this->assertSame($expected, $output7, $name); + } + } + + private function getParseOutput(Parser $parser, $code, $dumpPositions) { + $errors = new ErrorHandler\Collecting; + $stmts = $parser->parse($code, $errors); + + $output = ''; + foreach ($errors->getErrors() as $error) { + $output .= $this->formatErrorMessage($error, $code) . "\n"; + } + + if (null !== $stmts) { + $dumper = new NodeDumper(['dumpComments' => true, 'dumpPositions' => $dumpPositions]); + $output .= $dumper->dump($stmts, $code); + } + + return canonicalize($output); + } + + public function provideTestParse() { + return $this->getTests(__DIR__ . '/../code/parser', 'test'); + } + + private function formatErrorMessage(Error $e, $code) { + if ($e->hasColumnInfo()) { + return $e->getMessageWithColumnInfo($code); + } else { + return $e->getMessage(); + } + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeTestAbstract.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeTestAbstract.php new file mode 100644 index 0000000..369ee41 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CodeTestAbstract.php @@ -0,0 +1,61 @@ +getPathname(); + $fileContents = file_get_contents($fileName); + $fileContents = canonicalize($fileContents); + + // evaluate @@{expr}@@ expressions + $fileContents = preg_replace_callback( + '/@@\{(.*?)\}@@/', + function($matches) { + return eval('return ' . $matches[1] . ';'); + }, + $fileContents + ); + + // parse sections + $parts = preg_split("/\n-----(?:\n|$)/", $fileContents); + + // first part is the name + $name = array_shift($parts) . ' (' . $fileName . ')'; + $shortName = ltrim(str_replace($directory, '', $fileName), '/\\'); + + // multiple sections possible with always two forming a pair + $chunks = array_chunk($parts, 2); + foreach ($chunks as $i => $chunk) { + $dataSetName = $shortName . (count($chunks) > 1 ? '#' . $i : ''); + list($expected, $mode) = $this->extractMode($chunk[1]); + $tests[$dataSetName] = array($name, $chunk[0], $expected, $mode); + } + } + + return $tests; + } + + private function extractMode($expected) { + $firstNewLine = strpos($expected, "\n"); + if (false === $firstNewLine) { + $firstNewLine = strlen($expected); + } + + $firstLine = substr($expected, 0, $firstNewLine); + if (0 !== strpos($firstLine, '!!')) { + return [$expected, null]; + } + + $expected = (string) substr($expected, $firstNewLine + 1); + return [$expected, substr($firstLine, 2)]; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/CommentTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CommentTest.php new file mode 100644 index 0000000..081dd57 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/CommentTest.php @@ -0,0 +1,73 @@ +assertSame('/* Some comment */', $comment->getText()); + $this->assertSame('/* Some comment */', (string) $comment); + $this->assertSame(1, $comment->getLine()); + $this->assertSame(10, $comment->getFilePos()); + } + + /** + * @dataProvider provideTestReformatting + */ + public function testReformatting($commentText, $reformattedText) { + $comment = new Comment($commentText); + $this->assertSame($reformattedText, $comment->getReformattedText()); + } + + public function provideTestReformatting() { + return array( + array('// Some text' . "\n", '// Some text'), + array('/* Some text */', '/* Some text */'), + array( + '/** + * Some text. + * Some more text. + */', + '/** + * Some text. + * Some more text. + */' + ), + array( + '/* + Some text. + Some more text. + */', + '/* + Some text. + Some more text. +*/' + ), + array( + '/* Some text. + More text. + Even more text. */', + '/* Some text. + More text. + Even more text. */' + ), + array( + '/* Some text. + More text. + Indented text. */', + '/* Some text. + More text. + Indented text. */', + ), + // invalid comment -> no reformatting + array( + 'hallo + world', + 'hallo + world', + ), + ); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/CollectingTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/CollectingTest.php new file mode 100644 index 0000000..3742981 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/CollectingTest.php @@ -0,0 +1,22 @@ +assertFalse($errorHandler->hasErrors()); + $this->assertEmpty($errorHandler->getErrors()); + + $errorHandler->handleError($e1 = new Error('Test 1')); + $errorHandler->handleError($e2 = new Error('Test 2')); + $this->assertTrue($errorHandler->hasErrors()); + $this->assertSame([$e1, $e2], $errorHandler->getErrors()); + + $errorHandler->clearErrors(); + $this->assertFalse($errorHandler->hasErrors()); + $this->assertEmpty($errorHandler->getErrors()); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/ThrowingTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/ThrowingTest.php new file mode 100644 index 0000000..d7df7c2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorHandler/ThrowingTest.php @@ -0,0 +1,16 @@ +handleError(new Error('Test')); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorTest.php new file mode 100644 index 0000000..59e880c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ErrorTest.php @@ -0,0 +1,106 @@ + 10, + 'endLine' => 11, + ); + $error = new Error('Some error', $attributes); + + $this->assertSame('Some error', $error->getRawMessage()); + $this->assertSame($attributes, $error->getAttributes()); + $this->assertSame(10, $error->getStartLine()); + $this->assertSame(11, $error->getEndLine()); + $this->assertSame('Some error on line 10', $error->getMessage()); + + return $error; + } + + /** + * @depends testConstruct + */ + public function testSetMessageAndLine(Error $error) { + $error->setRawMessage('Some other error'); + $this->assertSame('Some other error', $error->getRawMessage()); + + $error->setStartLine(15); + $this->assertSame(15, $error->getStartLine()); + $this->assertSame('Some other error on line 15', $error->getMessage()); + } + + public function testUnknownLine() { + $error = new Error('Some error'); + + $this->assertSame(-1, $error->getStartLine()); + $this->assertSame(-1, $error->getEndLine()); + $this->assertSame('Some error on unknown line', $error->getMessage()); + } + + /** @dataProvider provideTestColumnInfo */ + public function testColumnInfo($code, $startPos, $endPos, $startColumn, $endColumn) { + $error = new Error('Some error', array( + 'startFilePos' => $startPos, + 'endFilePos' => $endPos, + )); + + $this->assertSame(true, $error->hasColumnInfo()); + $this->assertSame($startColumn, $error->getStartColumn($code)); + $this->assertSame($endColumn, $error->getEndColumn($code)); + + } + + public function provideTestColumnInfo() { + return array( + // Error at "bar" + array("assertSame(false, $error->hasColumnInfo()); + try { + $error->getStartColumn(''); + $this->fail('Expected RuntimeException'); + } catch (\RuntimeException $e) { + $this->assertSame('Error does not have column information', $e->getMessage()); + } + try { + $error->getEndColumn(''); + $this->fail('Expected RuntimeException'); + } catch (\RuntimeException $e) { + $this->assertSame('Error does not have column information', $e->getMessage()); + } + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Invalid position information + */ + public function testInvalidPosInfo() { + $error = new Error('Some error', array( + 'startFilePos' => 10, + 'endFilePos' => 11, + )); + $error->getStartColumn('code'); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Lexer/EmulativeTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Lexer/EmulativeTest.php new file mode 100644 index 0000000..f1fe618 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Lexer/EmulativeTest.php @@ -0,0 +1,133 @@ +getLexer(); + $lexer->startLexing('assertSame($expectedToken, $lexer->getNextToken()); + $this->assertSame(0, $lexer->getNextToken()); + } + + /** + * @dataProvider provideTestReplaceKeywords + */ + public function testNoReplaceKeywordsAfterObjectOperator($keyword) { + $lexer = $this->getLexer(); + $lexer->startLexing('' . $keyword); + + $this->assertSame(Tokens::T_OBJECT_OPERATOR, $lexer->getNextToken()); + $this->assertSame(Tokens::T_STRING, $lexer->getNextToken()); + $this->assertSame(0, $lexer->getNextToken()); + } + + public function provideTestReplaceKeywords() { + return array( + // PHP 5.5 + array('finally', Tokens::T_FINALLY), + array('yield', Tokens::T_YIELD), + + // PHP 5.4 + array('callable', Tokens::T_CALLABLE), + array('insteadof', Tokens::T_INSTEADOF), + array('trait', Tokens::T_TRAIT), + array('__TRAIT__', Tokens::T_TRAIT_C), + + // PHP 5.3 + array('__DIR__', Tokens::T_DIR), + array('goto', Tokens::T_GOTO), + array('namespace', Tokens::T_NAMESPACE), + array('__NAMESPACE__', Tokens::T_NS_C), + ); + } + + /** + * @dataProvider provideTestLexNewFeatures + */ + public function testLexNewFeatures($code, array $expectedTokens) { + $lexer = $this->getLexer(); + $lexer->startLexing('assertSame($expectedTokenType, $lexer->getNextToken($text)); + $this->assertSame($expectedTokenText, $text); + } + $this->assertSame(0, $lexer->getNextToken()); + } + + /** + * @dataProvider provideTestLexNewFeatures + */ + public function testLeaveStuffAloneInStrings($code) { + $stringifiedToken = '"' . addcslashes($code, '"\\') . '"'; + + $lexer = $this->getLexer(); + $lexer->startLexing('assertSame(Tokens::T_CONSTANT_ENCAPSED_STRING, $lexer->getNextToken($text)); + $this->assertSame($stringifiedToken, $text); + $this->assertSame(0, $lexer->getNextToken()); + } + + public function provideTestLexNewFeatures() { + return array( + array('yield from', array( + array(Tokens::T_YIELD_FROM, 'yield from'), + )), + array("yield\r\nfrom", array( + array(Tokens::T_YIELD_FROM, "yield\r\nfrom"), + )), + array('...', array( + array(Tokens::T_ELLIPSIS, '...'), + )), + array('**', array( + array(Tokens::T_POW, '**'), + )), + array('**=', array( + array(Tokens::T_POW_EQUAL, '**='), + )), + array('??', array( + array(Tokens::T_COALESCE, '??'), + )), + array('<=>', array( + array(Tokens::T_SPACESHIP, '<=>'), + )), + array('0b1010110', array( + array(Tokens::T_LNUMBER, '0b1010110'), + )), + array('0b1011010101001010110101010010101011010101010101101011001110111100', array( + array(Tokens::T_DNUMBER, '0b1011010101001010110101010010101011010101010101101011001110111100'), + )), + array('\\', array( + array(Tokens::T_NS_SEPARATOR, '\\'), + )), + array("<<<'NOWDOC'\nNOWDOC;\n", array( + array(Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"), + array(Tokens::T_END_HEREDOC, 'NOWDOC'), + array(ord(';'), ';'), + )), + array("<<<'NOWDOC'\nFoobar\nNOWDOC;\n", array( + array(Tokens::T_START_HEREDOC, "<<<'NOWDOC'\n"), + array(Tokens::T_ENCAPSED_AND_WHITESPACE, "Foobar\n"), + array(Tokens::T_END_HEREDOC, 'NOWDOC'), + array(ord(';'), ';'), + )), + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/LexerTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/LexerTest.php new file mode 100644 index 0000000..bf7a5d3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/LexerTest.php @@ -0,0 +1,265 @@ +markTestSkipped('HHVM does not throw warnings from token_get_all()'); + } + + $errorHandler = new ErrorHandler\Collecting(); + $lexer = $this->getLexer(['usedAttributes' => [ + 'comments', 'startLine', 'endLine', 'startFilePos', 'endFilePos' + ]]); + $lexer->startLexing($code, $errorHandler); + $errors = $errorHandler->getErrors(); + + $this->assertSame(count($messages), count($errors)); + for ($i = 0; $i < count($messages); $i++) { + $this->assertSame($messages[$i], $errors[$i]->getMessageWithColumnInfo($code)); + } + } + + public function provideTestError() { + return array( + array("getLexer($options); + $lexer->startLexing($code); + while ($id = $lexer->getNextToken($value, $startAttributes, $endAttributes)) { + $token = array_shift($tokens); + + $this->assertSame($token[0], $id); + $this->assertSame($token[1], $value); + $this->assertEquals($token[2], $startAttributes); + $this->assertEquals($token[3], $endAttributes); + } + } + + public function provideTestLex() { + return array( + // tests conversion of closing PHP tag and drop of whitespace and opening tags + array( + 'plaintext', + array(), + array( + array( + Tokens::T_STRING, 'tokens', + array('startLine' => 1), array('endLine' => 1) + ), + array( + ord(';'), '?>', + array('startLine' => 1), array('endLine' => 1) + ), + array( + Tokens::T_INLINE_HTML, 'plaintext', + array('startLine' => 1, 'hasLeadingNewline' => false), + array('endLine' => 1) + ), + ) + ), + // tests line numbers + array( + ' 2), array('endLine' => 2) + ), + array( + Tokens::T_STRING, 'token', + array('startLine' => 2), array('endLine' => 2) + ), + array( + ord('$'), '$', + array( + 'startLine' => 3, + 'comments' => array( + new Comment\Doc('/** doc' . "\n" . 'comment */', 2, 14), + ) + ), + array('endLine' => 3) + ), + ) + ), + // tests comment extraction + array( + ' 2, + 'comments' => array( + new Comment('/* comment */', 1, 6), + new Comment('// comment' . "\n", 1, 20), + new Comment\Doc('/** docComment 1 */', 2, 31), + new Comment\Doc('/** docComment 2 */', 2, 50), + ), + ), + array('endLine' => 2) + ), + ) + ), + // tests differing start and end line + array( + ' 1), array('endLine' => 2) + ), + ) + ), + // tests exact file offsets + array( + ' array('startFilePos', 'endFilePos')), + array( + array( + Tokens::T_CONSTANT_ENCAPSED_STRING, '"a"', + array('startFilePos' => 6), array('endFilePos' => 8) + ), + array( + ord(';'), ';', + array('startFilePos' => 9), array('endFilePos' => 9) + ), + array( + Tokens::T_CONSTANT_ENCAPSED_STRING, '"b"', + array('startFilePos' => 18), array('endFilePos' => 20) + ), + array( + ord(';'), ';', + array('startFilePos' => 21), array('endFilePos' => 21) + ), + ) + ), + // tests token offsets + array( + ' array('startTokenPos', 'endTokenPos')), + array( + array( + Tokens::T_CONSTANT_ENCAPSED_STRING, '"a"', + array('startTokenPos' => 1), array('endTokenPos' => 1) + ), + array( + ord(';'), ';', + array('startTokenPos' => 2), array('endTokenPos' => 2) + ), + array( + Tokens::T_CONSTANT_ENCAPSED_STRING, '"b"', + array('startTokenPos' => 5), array('endTokenPos' => 5) + ), + array( + ord(';'), ';', + array('startTokenPos' => 6), array('endTokenPos' => 6) + ), + ) + ), + // tests all attributes being disabled + array( + ' array()), + array( + array( + Tokens::T_VARIABLE, '$bar', + array(), array() + ), + array( + ord(';'), ';', + array(), array() + ) + ) + ), + // tests no tokens + array( + '', + array(), + array() + ), + ); + } + + /** + * @dataProvider provideTestHaltCompiler + */ + public function testHandleHaltCompiler($code, $remaining) { + $lexer = $this->getLexer(); + $lexer->startLexing($code); + + while (Tokens::T_HALT_COMPILER !== $lexer->getNextToken()); + + $this->assertSame($remaining, $lexer->handleHaltCompiler()); + $this->assertSame(0, $lexer->getNextToken()); + } + + public function provideTestHaltCompiler() { + return array( + array('Remaining Text', 'Remaining Text'), + //array('getLexer(); + $lexer->startLexing('getNextToken()); + $lexer->handleHaltCompiler(); + } + + public function testGetTokens() { + $code = 'getLexer(); + $lexer->startLexing($code); + $this->assertSame($expectedTokens, $lexer->getTokens()); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/NameTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/NameTest.php new file mode 100644 index 0000000..76a89c3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/NameTest.php @@ -0,0 +1,134 @@ +assertSame(array('foo', 'bar'), $name->parts); + + $name = new Name('foo\bar'); + $this->assertSame(array('foo', 'bar'), $name->parts); + + $name = new Name($name); + $this->assertSame(array('foo', 'bar'), $name->parts); + } + + public function testGet() { + $name = new Name('foo'); + $this->assertSame('foo', $name->getFirst()); + $this->assertSame('foo', $name->getLast()); + + $name = new Name('foo\bar'); + $this->assertSame('foo', $name->getFirst()); + $this->assertSame('bar', $name->getLast()); + } + + public function testToString() { + $name = new Name('foo\bar'); + + $this->assertSame('foo\bar', (string) $name); + $this->assertSame('foo\bar', $name->toString()); + } + + public function testSlice() { + $name = new Name('foo\bar\baz'); + $this->assertEquals(new Name('foo\bar\baz'), $name->slice(0)); + $this->assertEquals(new Name('bar\baz'), $name->slice(1)); + $this->assertNull($name->slice(3)); + $this->assertEquals(new Name('foo\bar\baz'), $name->slice(-3)); + $this->assertEquals(new Name('bar\baz'), $name->slice(-2)); + $this->assertEquals(new Name('foo\bar'), $name->slice(0, -1)); + $this->assertNull($name->slice(0, -3)); + $this->assertEquals(new Name('bar'), $name->slice(1, -1)); + $this->assertNull($name->slice(1, -2)); + $this->assertEquals(new Name('bar'), $name->slice(-2, 1)); + $this->assertEquals(new Name('bar'), $name->slice(-2, -1)); + $this->assertNull($name->slice(-2, -2)); + } + + /** + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Offset 4 is out of bounds + */ + public function testSliceOffsetTooLarge() { + (new Name('foo\bar\baz'))->slice(4); + } + + /** + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Offset -4 is out of bounds + */ + public function testSliceOffsetTooSmall() { + (new Name('foo\bar\baz'))->slice(-4); + } + + /** + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Length 4 is out of bounds + */ + public function testSliceLengthTooLarge() { + (new Name('foo\bar\baz'))->slice(0, 4); + } + + /** + * @expectedException \OutOfBoundsException + * @expectedExceptionMessage Length -4 is out of bounds + */ + public function testSliceLengthTooSmall() { + (new Name('foo\bar\baz'))->slice(0, -4); + } + + public function testConcat() { + $this->assertEquals(new Name('foo\bar\baz'), Name::concat('foo', 'bar\baz')); + $this->assertEquals( + new Name\FullyQualified('foo\bar'), + Name\FullyQualified::concat(['foo'], new Name('bar')) + ); + + $attributes = ['foo' => 'bar']; + $this->assertEquals( + new Name\Relative('foo\bar\baz', $attributes), + Name\Relative::concat(new Name\FullyQualified('foo\bar'), 'baz', $attributes) + ); + + $this->assertEquals(new Name('foo'), Name::concat(null, 'foo')); + $this->assertEquals(new Name('foo'), Name::concat('foo', null)); + $this->assertNull(Name::concat(null, null)); + } + + public function testIs() { + $name = new Name('foo'); + $this->assertTrue ($name->isUnqualified()); + $this->assertFalse($name->isQualified()); + $this->assertFalse($name->isFullyQualified()); + $this->assertFalse($name->isRelative()); + + $name = new Name('foo\bar'); + $this->assertFalse($name->isUnqualified()); + $this->assertTrue ($name->isQualified()); + $this->assertFalse($name->isFullyQualified()); + $this->assertFalse($name->isRelative()); + + $name = new Name\FullyQualified('foo'); + $this->assertFalse($name->isUnqualified()); + $this->assertFalse($name->isQualified()); + $this->assertTrue ($name->isFullyQualified()); + $this->assertFalse($name->isRelative()); + + $name = new Name\Relative('foo'); + $this->assertFalse($name->isUnqualified()); + $this->assertFalse($name->isQualified()); + $this->assertFalse($name->isFullyQualified()); + $this->assertTrue ($name->isRelative()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Expected string, array of parts or Name instance + */ + public function testInvalidArg() { + Name::concat('foo', new \stdClass); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/MagicConstTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/MagicConstTest.php new file mode 100644 index 0000000..3141f56 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/MagicConstTest.php @@ -0,0 +1,25 @@ +assertSame($name, $magicConst->getName()); + } + + public function provideTestGetName() { + return array( + array(new MagicConst\Class_, '__CLASS__'), + array(new MagicConst\Dir, '__DIR__'), + array(new MagicConst\File, '__FILE__'), + array(new MagicConst\Function_, '__FUNCTION__'), + array(new MagicConst\Line, '__LINE__'), + array(new MagicConst\Method, '__METHOD__'), + array(new MagicConst\Namespace_, '__NAMESPACE__'), + array(new MagicConst\Trait_, '__TRAIT__'), + ); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/StringTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/StringTest.php new file mode 100644 index 0000000..be39035 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Scalar/StringTest.php @@ -0,0 +1,61 @@ +assertSame( + $expected, + String_::parseEscapeSequences($string, $quote) + ); + } + + /** + * @dataProvider provideTestParse + */ + public function testCreate($expected, $string) { + $this->assertSame( + $expected, + String_::parse($string) + ); + } + + public function provideTestParseEscapeSequences() { + return array( + array('"', '\\"', '"'), + array('\\"', '\\"', '`'), + array('\\"\\`', '\\"\\`', null), + array("\\\$\n\r\t\f\v", '\\\\\$\n\r\t\f\v', null), + array("\x1B", '\e', null), + array(chr(255), '\xFF', null), + array(chr(255), '\377', null), + array(chr(0), '\400', null), + array("\0", '\0', null), + array('\xFF', '\\\\xFF', null), + ); + } + + public function provideTestParse() { + $tests = array( + array('A', '\'A\''), + array('A', 'b\'A\''), + array('A', '"A"'), + array('A', 'b"A"'), + array('\\', '\'\\\\\''), + array('\'', '\'\\\'\''), + ); + + foreach ($this->provideTestParseEscapeSequences() as $i => $test) { + // skip second and third tests, they aren't for double quotes + if ($i != 1 && $i != 2) { + $tests[] = array($test[0], '"' . $test[1] . '"'); + } + } + + return $tests; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassConstTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassConstTest.php new file mode 100644 index 0000000..610972c --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassConstTest.php @@ -0,0 +1,35 @@ +assertTrue($node->{'is' . $modifier}()); + } + + public function testNoModifiers() { + $node = new ClassConst(array(), 0); + + $this->assertTrue($node->isPublic()); + $this->assertFalse($node->isProtected()); + $this->assertFalse($node->isPrivate()); + $this->assertFalse($node->isStatic()); + } + + public function provideModifiers() { + return array( + array('public'), + array('protected'), + array('private'), + ); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassMethodTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassMethodTest.php new file mode 100644 index 0000000..fa8aed8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassMethodTest.php @@ -0,0 +1,63 @@ + constant('PhpParser\Node\Stmt\Class_::MODIFIER_' . strtoupper($modifier)) + )); + + $this->assertTrue($node->{'is' . $modifier}()); + } + + public function testNoModifiers() { + $node = new ClassMethod('foo', array('type' => 0)); + + $this->assertTrue($node->isPublic()); + $this->assertFalse($node->isProtected()); + $this->assertFalse($node->isPrivate()); + $this->assertFalse($node->isAbstract()); + $this->assertFalse($node->isFinal()); + $this->assertFalse($node->isStatic()); + } + + public function provideModifiers() { + return array( + array('public'), + array('protected'), + array('private'), + array('abstract'), + array('final'), + array('static'), + ); + } + + /** + * Checks that implicit public modifier detection for method is working + * + * @dataProvider implicitPublicModifiers + * + * @param integer $modifier Node type modifier + */ + public function testImplicitPublic($modifier) + { + $node = new ClassMethod('foo', array( + 'type' => constant('PhpParser\Node\Stmt\Class_::MODIFIER_' . strtoupper($modifier)) + )); + + $this->assertTrue($node->isPublic(), 'Node should be implicitly public'); + } + + public function implicitPublicModifiers() { + return array( + array('abstract'), + array('final'), + array('static'), + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassTest.php new file mode 100644 index 0000000..75d49e3 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/ClassTest.php @@ -0,0 +1,66 @@ + Class_::MODIFIER_ABSTRACT)); + $this->assertTrue($class->isAbstract()); + + $class = new Class_('Foo'); + $this->assertFalse($class->isAbstract()); + } + + public function testIsFinal() { + $class = new Class_('Foo', array('type' => Class_::MODIFIER_FINAL)); + $this->assertTrue($class->isFinal()); + + $class = new Class_('Foo'); + $this->assertFalse($class->isFinal()); + } + + public function testGetMethods() { + $methods = array( + new ClassMethod('foo'), + new ClassMethod('bar'), + new ClassMethod('fooBar'), + ); + $class = new Class_('Foo', array( + 'stmts' => array( + new TraitUse(array()), + $methods[0], + new ClassConst(array()), + $methods[1], + new Property(0, array()), + $methods[2], + ) + )); + + $this->assertSame($methods, $class->getMethods()); + } + + public function testGetMethod() { + $methodConstruct = new ClassMethod('__CONSTRUCT'); + $methodTest = new ClassMethod('test'); + $class = new Class_('Foo', array( + 'stmts' => array( + new ClassConst(array()), + $methodConstruct, + new Property(0, array()), + $methodTest, + ) + )); + + $this->assertSame($methodConstruct, $class->getMethod('__construct')); + $this->assertSame($methodTest, $class->getMethod('test')); + $this->assertNull($class->getMethod('nonExisting')); + } + + public function testDeprecatedTypeNode() { + $class = new Class_('Foo', array('type' => Class_::MODIFIER_ABSTRACT)); + $this->assertTrue($class->isAbstract()); + $this->assertSame(Class_::MODIFIER_ABSTRACT, $class->flags); + $this->assertSame(Class_::MODIFIER_ABSTRACT, $class->type); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/InterfaceTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/InterfaceTest.php new file mode 100644 index 0000000..c499058 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/InterfaceTest.php @@ -0,0 +1,26 @@ + array( + new Node\Stmt\ClassConst(array(new Node\Const_('C1', new Node\Scalar\String_('C1')))), + $methods[0], + new Node\Stmt\ClassConst(array(new Node\Const_('C2', new Node\Scalar\String_('C2')))), + $methods[1], + new Node\Stmt\ClassConst(array(new Node\Const_('C3', new Node\Scalar\String_('C3')))), + ) + )); + + $this->assertSame($methods, $interface->getMethods()); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/PropertyTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/PropertyTest.php new file mode 100644 index 0000000..bcfc0c6 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Node/Stmt/PropertyTest.php @@ -0,0 +1,44 @@ +assertTrue($node->{'is' . $modifier}()); + } + + public function testNoModifiers() { + $node = new Property(0, array()); + + $this->assertTrue($node->isPublic()); + $this->assertFalse($node->isProtected()); + $this->assertFalse($node->isPrivate()); + $this->assertFalse($node->isStatic()); + } + + public function testStaticImplicitlyPublic() { + $node = new Property(Class_::MODIFIER_STATIC, array()); + $this->assertTrue($node->isPublic()); + $this->assertFalse($node->isProtected()); + $this->assertFalse($node->isPrivate()); + $this->assertTrue($node->isStatic()); + } + + public function provideModifiers() { + return array( + array('public'), + array('protected'), + array('private'), + array('static'), + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeAbstractTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeAbstractTest.php new file mode 100644 index 0000000..7fd0a39 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeAbstractTest.php @@ -0,0 +1,274 @@ +subNode1 = $subNode1; + $this->subNode2 = $subNode2; + } + + public function getSubNodeNames() { + return array('subNode1', 'subNode2'); + } + + // This method is only overwritten because the node is located in an unusual namespace + public function getType() { + return 'Dummy'; + } +} + +class NodeAbstractTest extends \PHPUnit_Framework_TestCase +{ + public function provideNodes() { + $attributes = array( + 'startLine' => 10, + 'comments' => array( + new Comment('// Comment' . "\n"), + new Comment\Doc('/** doc comment */'), + ), + ); + + $node = new DummyNode('value1', 'value2', $attributes); + $node->notSubNode = 'value3'; + + return array( + array($attributes, $node), + ); + } + + /** + * @dataProvider provideNodes + */ + public function testConstruct(array $attributes, Node $node) { + $this->assertSame('Dummy', $node->getType()); + $this->assertSame(array('subNode1', 'subNode2'), $node->getSubNodeNames()); + $this->assertSame(10, $node->getLine()); + $this->assertSame('/** doc comment */', $node->getDocComment()->getText()); + $this->assertSame('value1', $node->subNode1); + $this->assertSame('value2', $node->subNode2); + $this->assertTrue(isset($node->subNode1)); + $this->assertTrue(isset($node->subNode2)); + $this->assertFalse(isset($node->subNode3)); + $this->assertSame($attributes, $node->getAttributes()); + + return $node; + } + + /** + * @dataProvider provideNodes + */ + public function testGetDocComment(array $attributes, Node $node) { + $this->assertSame('/** doc comment */', $node->getDocComment()->getText()); + array_pop($node->getAttribute('comments')); // remove doc comment + $this->assertNull($node->getDocComment()); + array_pop($node->getAttribute('comments')); // remove comment + $this->assertNull($node->getDocComment()); + } + + public function testSetDocComment() { + $node = new DummyNode(null, null, []); + + // Add doc comment to node without comments + $docComment = new Comment\Doc('/** doc */'); + $node->setDocComment($docComment); + $this->assertSame($docComment, $node->getDocComment()); + + // Replace it + $docComment = new Comment\Doc('/** doc 2 */'); + $node->setDocComment($docComment); + $this->assertSame($docComment, $node->getDocComment()); + + // Add docmment to node with other comments + $c1 = new Comment('/* foo */'); + $c2 = new Comment('/* bar */'); + $docComment = new Comment\Doc('/** baz */'); + $node->setAttribute('comments', [$c1, $c2]); + $node->setDocComment($docComment); + $this->assertSame([$c1, $c2, $docComment], $node->getAttribute('comments')); + } + + /** + * @dataProvider provideNodes + */ + public function testChange(array $attributes, Node $node) { + // change of line + $node->setLine(15); + $this->assertSame(15, $node->getLine()); + + // direct modification + $node->subNode = 'newValue'; + $this->assertSame('newValue', $node->subNode); + + // indirect modification + $subNode =& $node->subNode; + $subNode = 'newNewValue'; + $this->assertSame('newNewValue', $node->subNode); + + // removal + unset($node->subNode); + $this->assertFalse(isset($node->subNode)); + } + + /** + * @dataProvider provideNodes + */ + public function testIteration(array $attributes, Node $node) { + // Iteration is simple object iteration over properties, + // not over subnodes + $i = 0; + foreach ($node as $key => $value) { + if ($i === 0) { + $this->assertSame('subNode1', $key); + $this->assertSame('value1', $value); + } else if ($i === 1) { + $this->assertSame('subNode2', $key); + $this->assertSame('value2', $value); + } else if ($i === 2) { + $this->assertSame('notSubNode', $key); + $this->assertSame('value3', $value); + } else { + throw new \Exception; + } + $i++; + } + $this->assertSame(3, $i); + } + + public function testAttributes() { + /** @var $node Node */ + $node = $this->getMockForAbstractClass('PhpParser\NodeAbstract'); + + $this->assertEmpty($node->getAttributes()); + + $node->setAttribute('key', 'value'); + $this->assertTrue($node->hasAttribute('key')); + $this->assertSame('value', $node->getAttribute('key')); + + $this->assertFalse($node->hasAttribute('doesNotExist')); + $this->assertNull($node->getAttribute('doesNotExist')); + $this->assertSame('default', $node->getAttribute('doesNotExist', 'default')); + + $node->setAttribute('null', null); + $this->assertTrue($node->hasAttribute('null')); + $this->assertNull($node->getAttribute('null')); + $this->assertNull($node->getAttribute('null', 'default')); + + $this->assertSame( + array( + 'key' => 'value', + 'null' => null, + ), + $node->getAttributes() + ); + } + + public function testJsonSerialization() { + $code = <<<'PHP' +parse(canonicalize($code)); + $json = json_encode($stmts, JSON_PRETTY_PRINT); + $this->assertEquals(canonicalize($expected), canonicalize($json)); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeDumperTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeDumperTest.php new file mode 100644 index 0000000..9bb65a7 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeDumperTest.php @@ -0,0 +1,105 @@ +assertSame($this->canonicalize($dump), $this->canonicalize($dumper->dump($node))); + } + + public function provideTestDump() { + return array( + array( + array(), +'array( +)' + ), + array( + array('Foo', 'Bar', 'Key' => 'FooBar'), +'array( + 0: Foo + 1: Bar + Key: FooBar +)' + ), + array( + new Node\Name(array('Hallo', 'World')), +'Name( + parts: array( + 0: Hallo + 1: World + ) +)' + ), + array( + new Node\Expr\Array_(array( + new Node\Expr\ArrayItem(new Node\Scalar\String_('Foo')) + )), +'Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: Foo + ) + byRef: false + ) + ) +)' + ), + ); + } + + public function testDumpWithPositions() { + $parser = (new ParserFactory)->create( + ParserFactory::ONLY_PHP7, + new Lexer(['usedAttributes' => ['startLine', 'endLine', 'startFilePos', 'endFilePos']]) + ); + $dumper = new NodeDumper(['dumpPositions' => true]); + + $code = "parse($code); + $dump = $dumper->dump($stmts, $code); + + $this->assertSame($this->canonicalize($expected), $this->canonicalize($dump)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Can only dump nodes and arrays. + */ + public function testError() { + $dumper = new NodeDumper; + $dumper->dump(new \stdClass); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeTraverserTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeTraverserTest.php new file mode 100644 index 0000000..9d27edc --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeTraverserTest.php @@ -0,0 +1,267 @@ +getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + $visitor->expects($this->at(0))->method('beforeTraverse')->with($stmts); + $visitor->expects($this->at(1))->method('enterNode')->with($echoNode); + $visitor->expects($this->at(2))->method('enterNode')->with($str1Node); + $visitor->expects($this->at(3))->method('leaveNode')->with($str1Node); + $visitor->expects($this->at(4))->method('enterNode')->with($str2Node); + $visitor->expects($this->at(5))->method('leaveNode')->with($str2Node); + $visitor->expects($this->at(6))->method('leaveNode')->with($echoNode); + $visitor->expects($this->at(7))->method('afterTraverse')->with($stmts); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + + $this->assertEquals($stmts, $traverser->traverse($stmts)); + } + + public function testModifying() { + $str1Node = new String_('Foo'); + $str2Node = new String_('Bar'); + $printNode = new Expr\Print_($str1Node); + + // first visitor changes the node, second verifies the change + $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + // replace empty statements with string1 node + $visitor1->expects($this->at(0))->method('beforeTraverse')->with(array()) + ->will($this->returnValue(array($str1Node))); + $visitor2->expects($this->at(0))->method('beforeTraverse')->with(array($str1Node)); + + // replace string1 node with print node + $visitor1->expects($this->at(1))->method('enterNode')->with($str1Node) + ->will($this->returnValue($printNode)); + $visitor2->expects($this->at(1))->method('enterNode')->with($printNode); + + // replace string1 node with string2 node + $visitor1->expects($this->at(2))->method('enterNode')->with($str1Node) + ->will($this->returnValue($str2Node)); + $visitor2->expects($this->at(2))->method('enterNode')->with($str2Node); + + // replace string2 node with string1 node again + $visitor1->expects($this->at(3))->method('leaveNode')->with($str2Node) + ->will($this->returnValue($str1Node)); + $visitor2->expects($this->at(3))->method('leaveNode')->with($str1Node); + + // replace print node with string1 node again + $visitor1->expects($this->at(4))->method('leaveNode')->with($printNode) + ->will($this->returnValue($str1Node)); + $visitor2->expects($this->at(4))->method('leaveNode')->with($str1Node); + + // replace string1 node with empty statements again + $visitor1->expects($this->at(5))->method('afterTraverse')->with(array($str1Node)) + ->will($this->returnValue(array())); + $visitor2->expects($this->at(5))->method('afterTraverse')->with(array()); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor1); + $traverser->addVisitor($visitor2); + + // as all operations are reversed we end where we start + $this->assertEquals(array(), $traverser->traverse(array())); + } + + public function testRemove() { + $str1Node = new String_('Foo'); + $str2Node = new String_('Bar'); + + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + // remove the string1 node, leave the string2 node + $visitor->expects($this->at(2))->method('leaveNode')->with($str1Node) + ->will($this->returnValue(false)); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + + $this->assertEquals(array($str2Node), $traverser->traverse(array($str1Node, $str2Node))); + } + + public function testMerge() { + $strStart = new String_('Start'); + $strMiddle = new String_('End'); + $strEnd = new String_('Middle'); + $strR1 = new String_('Replacement 1'); + $strR2 = new String_('Replacement 2'); + + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + // replace strMiddle with strR1 and strR2 by merge + $visitor->expects($this->at(4))->method('leaveNode')->with($strMiddle) + ->will($this->returnValue(array($strR1, $strR2))); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + + $this->assertEquals( + array($strStart, $strR1, $strR2, $strEnd), + $traverser->traverse(array($strStart, $strMiddle, $strEnd)) + ); + } + + public function testDeepArray() { + $strNode = new String_('Foo'); + $stmts = array(array(array($strNode))); + + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(1))->method('enterNode')->with($strNode); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + + $this->assertEquals($stmts, $traverser->traverse($stmts)); + } + + public function testDontTraverseChildren() { + $strNode = new String_('str'); + $printNode = new Expr\Print_($strNode); + $varNode = new Expr\Variable('foo'); + $mulNode = new Expr\BinaryOp\Mul($varNode, $varNode); + $negNode = new Expr\UnaryMinus($mulNode); + $stmts = array($printNode, $negNode); + + $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + $visitor1->expects($this->at(1))->method('enterNode')->with($printNode) + ->will($this->returnValue(NodeTraverser::DONT_TRAVERSE_CHILDREN)); + $visitor2->expects($this->at(1))->method('enterNode')->with($printNode); + + $visitor1->expects($this->at(2))->method('leaveNode')->with($printNode); + $visitor2->expects($this->at(2))->method('leaveNode')->with($printNode); + + $visitor1->expects($this->at(3))->method('enterNode')->with($negNode); + $visitor2->expects($this->at(3))->method('enterNode')->with($negNode); + + $visitor1->expects($this->at(4))->method('enterNode')->with($mulNode); + $visitor2->expects($this->at(4))->method('enterNode')->with($mulNode) + ->will($this->returnValue(NodeTraverser::DONT_TRAVERSE_CHILDREN)); + + $visitor1->expects($this->at(5))->method('leaveNode')->with($mulNode); + $visitor2->expects($this->at(5))->method('leaveNode')->with($mulNode); + + $visitor1->expects($this->at(6))->method('leaveNode')->with($negNode); + $visitor2->expects($this->at(6))->method('leaveNode')->with($negNode); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor1); + $traverser->addVisitor($visitor2); + + $this->assertEquals($stmts, $traverser->traverse($stmts)); + } + + public function testStopTraversal() { + $varNode1 = new Expr\Variable('a'); + $varNode2 = new Expr\Variable('b'); + $varNode3 = new Expr\Variable('c'); + $mulNode = new Expr\BinaryOp\Mul($varNode1, $varNode2); + $printNode = new Expr\Print_($varNode3); + $stmts = [$mulNode, $printNode]; + + // From enterNode() with array parent + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(1))->method('enterNode')->with($mulNode) + ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); + $visitor->expects($this->at(2))->method('afterTraverse'); + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $this->assertEquals($stmts, $traverser->traverse($stmts)); + + // From enterNode with Node parent + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(2))->method('enterNode')->with($varNode1) + ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); + $visitor->expects($this->at(3))->method('afterTraverse'); + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $this->assertEquals($stmts, $traverser->traverse($stmts)); + + // From leaveNode with Node parent + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(3))->method('leaveNode')->with($varNode1) + ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); + $visitor->expects($this->at(4))->method('afterTraverse'); + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $this->assertEquals($stmts, $traverser->traverse($stmts)); + + // From leaveNode with array parent + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(6))->method('leaveNode')->with($mulNode) + ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); + $visitor->expects($this->at(7))->method('afterTraverse'); + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $this->assertEquals($stmts, $traverser->traverse($stmts)); + + // Check that pending array modifications are still carried out + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->expects($this->at(6))->method('leaveNode')->with($mulNode) + ->will($this->returnValue(NodeTraverser::REMOVE_NODE)); + $visitor->expects($this->at(7))->method('enterNode')->with($printNode) + ->will($this->returnValue(NodeTraverser::STOP_TRAVERSAL)); + $visitor->expects($this->at(8))->method('afterTraverse'); + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor); + $this->assertEquals([$printNode], $traverser->traverse($stmts)); + + } + + public function testRemovingVisitor() { + $visitor1 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor2 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor3 = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + + $traverser = new NodeTraverser; + $traverser->addVisitor($visitor1); + $traverser->addVisitor($visitor2); + $traverser->addVisitor($visitor3); + + $preExpected = array($visitor1, $visitor2, $visitor3); + $this->assertAttributeSame($preExpected, 'visitors', $traverser, 'The appropriate visitors have not been added'); + + $traverser->removeVisitor($visitor2); + + $postExpected = array(0 => $visitor1, 2 => $visitor3); + $this->assertAttributeSame($postExpected, 'visitors', $traverser, 'The appropriate visitors are not present after removal'); + } + + public function testNoCloneNodes() { + $stmts = array(new Node\Stmt\Echo_(array(new String_('Foo'), new String_('Bar')))); + + $traverser = new NodeTraverser; + + $this->assertSame($stmts, $traverser->traverse($stmts)); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage leaveNode() may only return an array if the parent structure is an array + */ + public function testReplaceByArrayOnlyAllowedIfParentIsArray() { + $stmts = array(new Node\Expr\UnaryMinus(new Node\Scalar\LNumber(42))); + + $visitor = $this->getMockBuilder('PhpParser\NodeVisitor')->getMock(); + $visitor->method('leaveNode')->willReturn(array(new Node\Scalar\DNumber(42.0))); + + $traverser = new NodeTraverser(); + $traverser->addVisitor($visitor); + $traverser->traverse($stmts); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php new file mode 100644 index 0000000..0313374 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/NodeVisitor/NameResolverTest.php @@ -0,0 +1,468 @@ +addVisitor(new NameResolver); + + $stmts = $parser->parse($code); + $stmts = $traverser->traverse($stmts); + + $this->assertSame( + $this->canonicalize($expectedCode), + $prettyPrinter->prettyPrint($stmts) + ); + } + + /** + * @covers PhpParser\NodeVisitor\NameResolver + */ + public function testResolveLocations() { + $code = <<<'EOC' +addVisitor(new NameResolver); + + $stmts = $parser->parse($code); + $stmts = $traverser->traverse($stmts); + + $this->assertSame( + $this->canonicalize($expectedCode), + $prettyPrinter->prettyPrint($stmts) + ); + } + + public function testNoResolveSpecialName() { + $stmts = array(new Node\Expr\New_(new Name('self'))); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + + $this->assertEquals($stmts, $traverser->traverse($stmts)); + } + + public function testAddDeclarationNamespacedName() { + $nsStmts = array( + new Stmt\Class_('A'), + new Stmt\Interface_('B'), + new Stmt\Function_('C'), + new Stmt\Const_(array( + new Node\Const_('D', new Node\Scalar\LNumber(42)) + )), + new Stmt\Trait_('E'), + new Expr\New_(new Stmt\Class_(null)), + ); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + + $stmts = $traverser->traverse([new Stmt\Namespace_(new Name('NS'), $nsStmts)]); + $this->assertSame('NS\\A', (string) $stmts[0]->stmts[0]->namespacedName); + $this->assertSame('NS\\B', (string) $stmts[0]->stmts[1]->namespacedName); + $this->assertSame('NS\\C', (string) $stmts[0]->stmts[2]->namespacedName); + $this->assertSame('NS\\D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName); + $this->assertSame('NS\\E', (string) $stmts[0]->stmts[4]->namespacedName); + $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class); + + $stmts = $traverser->traverse([new Stmt\Namespace_(null, $nsStmts)]); + $this->assertSame('A', (string) $stmts[0]->stmts[0]->namespacedName); + $this->assertSame('B', (string) $stmts[0]->stmts[1]->namespacedName); + $this->assertSame('C', (string) $stmts[0]->stmts[2]->namespacedName); + $this->assertSame('D', (string) $stmts[0]->stmts[3]->consts[0]->namespacedName); + $this->assertSame('E', (string) $stmts[0]->stmts[4]->namespacedName); + $this->assertObjectNotHasAttribute('namespacedName', $stmts[0]->stmts[5]->class); + } + + public function testAddRuntimeResolvedNamespacedName() { + $stmts = array( + new Stmt\Namespace_(new Name('NS'), array( + new Expr\FuncCall(new Name('foo')), + new Expr\ConstFetch(new Name('FOO')), + )), + new Stmt\Namespace_(null, array( + new Expr\FuncCall(new Name('foo')), + new Expr\ConstFetch(new Name('FOO')), + )), + ); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + $stmts = $traverser->traverse($stmts); + + $this->assertSame('NS\\foo', (string) $stmts[0]->stmts[0]->name->getAttribute('namespacedName')); + $this->assertSame('NS\\FOO', (string) $stmts[0]->stmts[1]->name->getAttribute('namespacedName')); + + $this->assertFalse($stmts[1]->stmts[0]->name->hasAttribute('namespacedName')); + $this->assertFalse($stmts[1]->stmts[1]->name->hasAttribute('namespacedName')); + } + + /** + * @dataProvider provideTestError + */ + public function testError(Node $stmt, $errorMsg) { + $this->setExpectedException('PhpParser\Error', $errorMsg); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + $traverser->traverse(array($stmt)); + } + + public function provideTestError() { + return array( + array( + new Stmt\Use_(array( + new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), + new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), + ), Stmt\Use_::TYPE_NORMAL), + 'Cannot use C\D as B because the name is already in use on line 2' + ), + array( + new Stmt\Use_(array( + new Stmt\UseUse(new Name('a\b'), 'b', 0, array('startLine' => 1)), + new Stmt\UseUse(new Name('c\d'), 'B', 0, array('startLine' => 2)), + ), Stmt\Use_::TYPE_FUNCTION), + 'Cannot use function c\d as B because the name is already in use on line 2' + ), + array( + new Stmt\Use_(array( + new Stmt\UseUse(new Name('A\B'), 'B', 0, array('startLine' => 1)), + new Stmt\UseUse(new Name('C\D'), 'B', 0, array('startLine' => 2)), + ), Stmt\Use_::TYPE_CONSTANT), + 'Cannot use const C\D as B because the name is already in use on line 2' + ), + array( + new Expr\New_(new Name\FullyQualified('self', array('startLine' => 3))), + "'\\self' is an invalid class name on line 3" + ), + array( + new Expr\New_(new Name\Relative('self', array('startLine' => 3))), + "'\\self' is an invalid class name on line 3" + ), + array( + new Expr\New_(new Name\FullyQualified('PARENT', array('startLine' => 3))), + "'\\PARENT' is an invalid class name on line 3" + ), + array( + new Expr\New_(new Name\Relative('STATIC', array('startLine' => 3))), + "'\\STATIC' is an invalid class name on line 3" + ), + ); + } + + public function testClassNameIsCaseInsensitive() + { + $source = <<<'EOC' +parse($source); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + + $stmts = $traverser->traverse($stmts); + $stmt = $stmts[0]; + + $this->assertSame(array('Bar', 'Baz'), $stmt->stmts[1]->expr->class->parts); + } + + public function testSpecialClassNamesAreCaseInsensitive() { + $source = <<<'EOC' +parse($source); + + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver); + + $stmts = $traverser->traverse($stmts); + $classStmt = $stmts[0]; + $methodStmt = $classStmt->stmts[0]->stmts[0]; + + $this->assertSame('SELF', (string)$methodStmt->stmts[0]->class); + $this->assertSame('PARENT', (string)$methodStmt->stmts[1]->class); + $this->assertSame('STATIC', (string)$methodStmt->stmts[2]->class); + } + + public function testAddOriginalNames() { + $traverser = new PhpParser\NodeTraverser; + $traverser->addVisitor(new NameResolver(null, ['preserveOriginalNames' => true])); + + $n1 = new Name('Bar'); + $n2 = new Name('bar'); + $origStmts = [ + new Stmt\Namespace_(new Name('Foo'), [ + new Expr\ClassConstFetch($n1, 'FOO'), + new Expr\FuncCall($n2), + ]) + ]; + + $stmts = $traverser->traverse($origStmts); + + $this->assertSame($n1, $stmts[0]->stmts[0]->class->getAttribute('originalName')); + $this->assertSame($n2, $stmts[0]->stmts[1]->name->getAttribute('originalName')); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/MultipleTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/MultipleTest.php new file mode 100644 index 0000000..01d3b60 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/MultipleTest.php @@ -0,0 +1,94 @@ + []]); + return new Multiple([new Php7($lexer), new Php5($lexer)]); + } + + private function getPrefer5() { + $lexer = new Lexer(['usedAttributes' => []]); + return new Multiple([new Php5($lexer), new Php7($lexer)]); + } + + /** @dataProvider provideTestParse */ + public function testParse($code, Multiple $parser, $expected) { + $this->assertEquals($expected, $parser->parse($code)); + } + + public function provideTestParse() { + return [ + [ + // PHP 7 only code + 'getPrefer5(), + [ + new Stmt\Class_('Test', ['stmts' => [ + new Stmt\ClassMethod('function') + ]]), + ] + ], + [ + // PHP 5 only code + 'b;', + $this->getPrefer7(), + [ + new Stmt\Global_([ + new Expr\Variable(new Expr\PropertyFetch(new Expr\Variable('a'), 'b')) + ]) + ] + ], + [ + // Different meaning (PHP 5) + 'getPrefer5(), + [ + new Expr\Variable( + new Expr\ArrayDimFetch(new Expr\Variable('a'), LNumber::fromString('0')) + ) + ] + ], + [ + // Different meaning (PHP 7) + 'getPrefer7(), + [ + new Expr\ArrayDimFetch( + new Expr\Variable(new Expr\Variable('a')), LNumber::fromString('0') + ) + ] + ], + ]; + } + + public function testThrownError() { + $this->setExpectedException('PhpParser\Error', 'FAIL A'); + + $parserA = $this->getMockBuilder('PhpParser\Parser')->getMock(); + $parserA->expects($this->at(0)) + ->method('parse')->will($this->throwException(new Error('FAIL A'))); + + $parserB = $this->getMockBuilder('PhpParser\Parser')->getMock(); + $parserB->expects($this->at(0)) + ->method('parse')->will($this->throwException(new Error('FAIL B'))); + + $parser = new Multiple([$parserA, $parserB]); + $parser->parse('dummy'); + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/Php5Test.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/Php5Test.php new file mode 100644 index 0000000..58c4e61 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Parser/Php5Test.php @@ -0,0 +1,14 @@ +assertInstanceOf($expected, (new ParserFactory)->create($kind, $lexer)); + } + + public function provideTestCreate() { + $lexer = new Lexer(); + return [ + [ + ParserFactory::PREFER_PHP7, $lexer, + 'PhpParser\Parser\Multiple' + ], + [ + ParserFactory::PREFER_PHP5, null, + 'PhpParser\Parser\Multiple' + ], + [ + ParserFactory::ONLY_PHP7, null, + 'PhpParser\Parser\Php7' + ], + [ + ParserFactory::ONLY_PHP5, $lexer, + 'PhpParser\Parser\Php5' + ] + ]; + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/ParserTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ParserTest.php new file mode 100644 index 0000000..0dabba2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/ParserTest.php @@ -0,0 +1,184 @@ +getParser(new Lexer()); + $parser->parse('getParser(new Lexer()); + $parser->parse('getParser(new Lexer()); + $parser->parse(' array( + 'comments', 'startLine', 'endLine', + 'startTokenPos', 'endTokenPos', + ) + )); + + $code = <<<'EOC' +getParser($lexer); + $stmts = $parser->parse($code); + + /** @var \PhpParser\Node\Stmt\Function_ $fn */ + $fn = $stmts[0]; + $this->assertInstanceOf('PhpParser\Node\Stmt\Function_', $fn); + $this->assertEquals(array( + 'comments' => array( + new Comment\Doc('/** Doc comment */', 2, 6), + ), + 'startLine' => 3, + 'endLine' => 7, + 'startTokenPos' => 3, + 'endTokenPos' => 21, + ), $fn->getAttributes()); + + $param = $fn->params[0]; + $this->assertInstanceOf('PhpParser\Node\Param', $param); + $this->assertEquals(array( + 'startLine' => 3, + 'endLine' => 3, + 'startTokenPos' => 7, + 'endTokenPos' => 7, + ), $param->getAttributes()); + + /** @var \PhpParser\Node\Stmt\Echo_ $echo */ + $echo = $fn->stmts[0]; + $this->assertInstanceOf('PhpParser\Node\Stmt\Echo_', $echo); + $this->assertEquals(array( + 'comments' => array( + new Comment("// Line\n", 4, 49), + new Comment("// Comments\n", 5, 61), + ), + 'startLine' => 6, + 'endLine' => 6, + 'startTokenPos' => 16, + 'endTokenPos' => 19, + ), $echo->getAttributes()); + + /** @var \PhpParser\Node\Expr\Variable $var */ + $var = $echo->exprs[0]; + $this->assertInstanceOf('PhpParser\Node\Expr\Variable', $var); + $this->assertEquals(array( + 'startLine' => 6, + 'endLine' => 6, + 'startTokenPos' => 18, + 'endTokenPos' => 18, + ), $var->getAttributes()); + } + + /** + * @expectedException \RangeException + * @expectedExceptionMessage The lexer returned an invalid token (id=999, value=foobar) + */ + public function testInvalidToken() { + $lexer = new InvalidTokenLexer; + $parser = $this->getParser($lexer); + $parser->parse('dummy'); + } + + /** + * @dataProvider provideTestExtraAttributes + */ + public function testExtraAttributes($code, $expectedAttributes) { + $parser = $this->getParser(new Lexer); + $stmts = $parser->parse("getAttributes(); + foreach ($expectedAttributes as $name => $value) { + $this->assertSame($value, $attributes[$name]); + } + } + + public function provideTestExtraAttributes() { + return array( + array('0', ['kind' => Scalar\LNumber::KIND_DEC]), + array('9', ['kind' => Scalar\LNumber::KIND_DEC]), + array('07', ['kind' => Scalar\LNumber::KIND_OCT]), + array('0xf', ['kind' => Scalar\LNumber::KIND_HEX]), + array('0XF', ['kind' => Scalar\LNumber::KIND_HEX]), + array('0b1', ['kind' => Scalar\LNumber::KIND_BIN]), + array('0B1', ['kind' => Scalar\LNumber::KIND_BIN]), + array('[]', ['kind' => Expr\Array_::KIND_SHORT]), + array('array()', ['kind' => Expr\Array_::KIND_LONG]), + array("'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]), + array("b'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]), + array("B'foo'", ['kind' => String_::KIND_SINGLE_QUOTED]), + array('"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array('b"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array('B"foo"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array('"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array('b"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array('B"foo$bar"', ['kind' => String_::KIND_DOUBLE_QUOTED]), + array("<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']), + array("<< String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("<<<\"STR\"\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("b<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']), + array("B<<<'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']), + array("<<< \t 'STR'\nSTR\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']), + // HHVM doesn't support this due to a lexer bug + // (https://github.com/facebook/hhvm/issues/6970) + // array("<<<'\xff'\n\xff\n", ['kind' => String_::KIND_NOWDOC, 'docLabel' => "\xff"]), + array("<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("b<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("B<<<\"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("<<< \t \"STR\"\n\$a\nSTR\n", ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']), + array("die", ['kind' => Expr\Exit_::KIND_DIE]), + array("die('done')", ['kind' => Expr\Exit_::KIND_DIE]), + array("exit", ['kind' => Expr\Exit_::KIND_EXIT]), + array("exit(1)", ['kind' => Expr\Exit_::KIND_EXIT]), + array("?>Foo", ['hasLeadingNewline' => false]), + array("?>\nFoo", ['hasLeadingNewline' => true]), + array("namespace Foo;", ['kind' => Node\Stmt\Namespace_::KIND_SEMICOLON]), + array("namespace Foo {}", ['kind' => Node\Stmt\Namespace_::KIND_BRACED]), + array("namespace {}", ['kind' => Node\Stmt\Namespace_::KIND_BRACED]), + ); + } +} + +class InvalidTokenLexer extends Lexer { + public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) { + $value = 'foobar'; + return 999; + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php new file mode 100644 index 0000000..908c18b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/PrettyPrinterTest.php @@ -0,0 +1,207 @@ +parseModeLine($modeLine); + $prettyPrinter = new Standard($options); + + try { + $output5 = canonicalize($prettyPrinter->$method($parser5->parse($code))); + } catch (Error $e) { + $output5 = null; + if ('php7' !== $version) { + throw $e; + } + } + + try { + $output7 = canonicalize($prettyPrinter->$method($parser7->parse($code))); + } catch (Error $e) { + $output7 = null; + if ('php5' !== $version) { + throw $e; + } + } + + if ('php5' === $version) { + $this->assertSame($expected, $output5, $name); + $this->assertNotSame($expected, $output7, $name); + } else if ('php7' === $version) { + $this->assertSame($expected, $output7, $name); + $this->assertNotSame($expected, $output5, $name); + } else { + $this->assertSame($expected, $output5, $name); + $this->assertSame($expected, $output7, $name); + } + } + + /** + * @dataProvider provideTestPrettyPrint + * @covers PhpParser\PrettyPrinter\Standard + */ + public function testPrettyPrint($name, $code, $expected, $mode) { + $this->doTestPrettyPrintMethod('prettyPrint', $name, $code, $expected, $mode); + } + + /** + * @dataProvider provideTestPrettyPrintFile + * @covers PhpParser\PrettyPrinter\Standard + */ + public function testPrettyPrintFile($name, $code, $expected, $mode) { + $this->doTestPrettyPrintMethod('prettyPrintFile', $name, $code, $expected, $mode); + } + + public function provideTestPrettyPrint() { + return $this->getTests(__DIR__ . '/../code/prettyPrinter', 'test'); + } + + public function provideTestPrettyPrintFile() { + return $this->getTests(__DIR__ . '/../code/prettyPrinter', 'file-test'); + } + + public function testPrettyPrintExpr() { + $prettyPrinter = new Standard; + $expr = new Expr\BinaryOp\Mul( + new Expr\BinaryOp\Plus(new Expr\Variable('a'), new Expr\Variable('b')), + new Expr\Variable('c') + ); + $this->assertEquals('($a + $b) * $c', $prettyPrinter->prettyPrintExpr($expr)); + + $expr = new Expr\Closure(array( + 'stmts' => array(new Stmt\Return_(new String_("a\nb"))) + )); + $this->assertEquals("function () {\n return 'a\nb';\n}", $prettyPrinter->prettyPrintExpr($expr)); + } + + public function testCommentBeforeInlineHTML() { + $prettyPrinter = new PrettyPrinter\Standard; + $comment = new Comment\Doc("/**\n * This is a comment\n */"); + $stmts = [new Stmt\InlineHTML('Hello World!', ['comments' => [$comment]])]; + $expected = "\nHello World!"; + $this->assertSame($expected, $prettyPrinter->prettyPrintFile($stmts)); + } + + private function parseModeLine($modeLine) { + $parts = explode(' ', $modeLine, 2); + $version = isset($parts[0]) ? $parts[0] : 'both'; + $options = isset($parts[1]) ? json_decode($parts[1], true) : []; + return [$version, $options]; + } + + public function testArraySyntaxDefault() { + $prettyPrinter = new Standard(['shortArraySyntax' => true]); + $expr = new Expr\Array_([ + new Expr\ArrayItem(new String_('val'), new String_('key')) + ]); + $expected = "['key' => 'val']"; + $this->assertSame($expected, $prettyPrinter->prettyPrintExpr($expr)); + } + + /** + * @dataProvider provideTestKindAttributes + */ + public function testKindAttributes($node, $expected) { + $prttyPrinter = new PrettyPrinter\Standard; + $result = $prttyPrinter->prettyPrintExpr($node); + $this->assertSame($expected, $result); + } + + public function provideTestKindAttributes() { + $nowdoc = ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']; + $heredoc = ['kind' => String_::KIND_HEREDOC, 'docLabel' => 'STR']; + return [ + // Defaults to single quoted + [new String_('foo'), "'foo'"], + // Explicit single/double quoted + [new String_('foo', ['kind' => String_::KIND_SINGLE_QUOTED]), "'foo'"], + [new String_('foo', ['kind' => String_::KIND_DOUBLE_QUOTED]), '"foo"'], + // Fallback from doc string if no label + [new String_('foo', ['kind' => String_::KIND_NOWDOC]), "'foo'"], + [new String_('foo', ['kind' => String_::KIND_HEREDOC]), '"foo"'], + // Fallback if string contains label + [new String_("A\nB\nC", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'A']), "'A\nB\nC'"], + [new String_("A\nB\nC", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'B']), "'A\nB\nC'"], + [new String_("A\nB\nC", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'C']), "'A\nB\nC'"], + [new String_("STR;", ['kind' => String_::KIND_NOWDOC, 'docLabel' => 'STR']), "'STR;'"], + // Doc string if label not contained (or not in ending position) + [new String_("foo", $nowdoc), "<<<'STR'\nfoo\nSTR\n"], + [new String_("foo", $heredoc), "<<prettyPrintExpr($node); + $this->assertSame($expected, $result); + } + + public function provideTestUnnaturalLiterals() { + return [ + [new LNumber(-1), '-1'], + [new LNumber(-PHP_INT_MAX - 1), '(-' . PHP_INT_MAX . '-1)'], + [new LNumber(-1, ['kind' => LNumber::KIND_BIN]), '-0b1'], + [new LNumber(-1, ['kind' => LNumber::KIND_OCT]), '-01'], + [new LNumber(-1, ['kind' => LNumber::KIND_HEX]), '-0x1'], + [new DNumber(\INF), '\INF'], + [new DNumber(-\INF), '-\INF'], + [new DNumber(-\NAN), '\NAN'], + ]; + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot pretty-print AST with Error nodes + */ + public function testPrettyPrintWithError() { + $stmts = [new Expr\PropertyFetch(new Expr\Variable('a'), new Expr\Error())]; + $prettyPrinter = new PrettyPrinter\Standard; + $prettyPrinter->prettyPrint($stmts); + } + + /** + * @expectedException \LogicException + * @expectedExceptionMessage Cannot pretty-print AST with Error nodes + */ + public function testPrettyPrintWithErrorInClassConstFetch() { + $stmts = [new Expr\ClassConstFetch(new Name('Foo'), new Expr\Error())]; + $prettyPrinter = new PrettyPrinter\Standard; + $prettyPrinter->prettyPrint($stmts); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Serializer/XMLTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Serializer/XMLTest.php new file mode 100644 index 0000000..e1186f4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Serializer/XMLTest.php @@ -0,0 +1,172 @@ + + */ + public function testSerialize() { + $code = << + + + + + 4 + + + + // comment + + /** doc comment */ + + + + 6 + + + + + + functionName + + + + + + 4 + + + 4 + + + + + + + + + + + + a + + + + + 4 + + + 4 + + + 10 + + + 0 + + + + + + + 4 + + + 4 + + + + + + + + + + + + b + + + + + 4 + + + 4 + + + 1 + + + + + + + + + + + + + + 5 + + + 5 + + + + + + 5 + + + 5 + + + 1 + + + Foo + + + + + + + + + + +XML; + + $parser = new PhpParser\Parser\Php7(new PhpParser\Lexer); + $serializer = new XML; + + $code = str_replace("\r\n", "\n", $code); + $stmts = $parser->parse($code); + $this->assertXmlStringEqualsXmlString($xml, $serializer->serialize($stmts)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Unexpected node type + */ + public function testError() { + $serializer = new XML; + $serializer->serialize(array(new \stdClass)); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/PhpParser/Unserializer/XMLTest.php b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Unserializer/XMLTest.php new file mode 100644 index 0000000..3bc86db --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/PhpParser/Unserializer/XMLTest.php @@ -0,0 +1,150 @@ + + + + + 1 + + + + // comment + + /** doc comment */ + + + + Test + + + +XML; + + $unserializer = new XML; + $this->assertEquals( + new Scalar\String_('Test', array( + 'startLine' => 1, + 'comments' => array( + new Comment('// comment' . "\n", 2), + new Comment\Doc('/** doc comment */', 3), + ), + )), + $unserializer->unserialize($xml) + ); + } + + public function testEmptyNode() { + $xml = << + + + +XML; + + $unserializer = new XML; + + $this->assertEquals( + new Scalar\MagicConst\Class_, + $unserializer->unserialize($xml) + ); + } + + public function testScalars() { + $xml = << + + + + + test + + + 1 + 1 + 1.5 + + + + + +XML; + $result = array( + array(), array(), + 'test', '', '', + 1, + 1, 1.5, + true, false, null + ); + + $unserializer = new XML; + $this->assertEquals($result, $unserializer->unserialize($xml)); + } + + /** + * @expectedException \DomainException + * @expectedExceptionMessage AST root element not found + */ + public function testWrongRootElementError() { + $xml = << + +XML; + + $unserializer = new XML; + $unserializer->unserialize($xml); + } + + /** + * @dataProvider provideTestErrors + */ + public function testErrors($xml, $errorMsg) { + $this->setExpectedException('DomainException', $errorMsg); + + $xml = << + + $xml + +XML; + + $unserializer = new XML; + $unserializer->unserialize($xml); + } + + public function provideTestErrors() { + return array( + array('test', '"true" scalar must be empty'), + array('test', '"false" scalar must be empty'), + array('test', '"null" scalar must be empty'), + array('bar', 'Unknown scalar type "foo"'), + array('x', '"x" is not a valid int'), + array('x', '"x" is not a valid float'), + array('', 'Expected node or scalar'), + array('test', 'Unexpected node of type "foo:bar"'), + array( + 'test', + 'Expected sub node or attribute, got node of type "foo:bar"' + ), + array( + '', + 'Expected node or scalar' + ), + array( + '', + 'Unknown node type "Foo"' + ), + ); + } +} diff --git a/www/multitube/vendor/nikic/php-parser/test/bootstrap.php b/www/multitube/vendor/nikic/php-parser/test/bootstrap.php new file mode 100644 index 0000000..9526b64 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/bootstrap.php @@ -0,0 +1,20 @@ + +----- +array( + 0: Stmt_Nop( + comments: array( + 0: /** doc */ + 1: /* foobar */ + 2: // foo + 3: // bar + ) + ) +) +----- + +; +----- +!!positions +Syntax error, unexpected ';', expecting T_STRING or T_VARIABLE or '{' or '$' from 3:1 to 3:1 +array( + 0: Expr_PropertyFetch[2:1 - 2:6]( + var: Expr_Variable[2:1 - 2:4]( + name: foo + ) + name: Expr_Error[3:1 - 2:6]( + ) + ) +) +----- + +} +----- +!!positions +Syntax error, unexpected '}', expecting T_STRING or T_VARIABLE or '{' or '$' from 4:1 to 4:1 +array( + 0: Stmt_Function[2:1 - 4:1]( + byRef: false + name: foo + params: array( + ) + returnType: null + stmts: array( + 0: Expr_PropertyFetch[3:5 - 3:10]( + var: Expr_Variable[3:5 - 3:8]( + name: bar + ) + name: Expr_Error[4:1 - 3:10]( + ) + ) + ) + ) +) +----- + 'd', 'e' => &$f); + +// short array syntax +[]; +[1, 2, 3]; +['a' => 'b']; +----- +array( + 0: Expr_Array( + items: array( + ) + ) + 1: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: a + ) + byRef: false + ) + ) + ) + 2: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: a + ) + byRef: false + ) + ) + ) + 3: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: a + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Scalar_String( + value: b + ) + byRef: false + ) + ) + ) + 4: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: a + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: true + ) + 2: Expr_ArrayItem( + key: Scalar_String( + value: c + ) + value: Scalar_String( + value: d + ) + byRef: false + ) + 3: Expr_ArrayItem( + key: Scalar_String( + value: e + ) + value: Expr_Variable( + name: f + ) + byRef: true + ) + ) + ) + 5: Expr_Array( + items: array( + ) + comments: array( + 0: // short array syntax + ) + ) + 6: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 1 + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 2 + ) + byRef: false + ) + 2: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 3 + ) + byRef: false + ) + ) + ) + 7: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Scalar_String( + value: b + ) + byRef: false + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/arrayDestructuring.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/arrayDestructuring.test new file mode 100644 index 0000000..4ca76b2 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/arrayDestructuring.test @@ -0,0 +1,144 @@ +Array destructuring +----- + $b, 'b' => $a] = $baz; +----- +!!php7 +array( + 0: Expr_Assign( + var: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + ) + ) + expr: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: c + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: d + ) + byRef: false + ) + ) + ) + ) + 1: Expr_Assign( + var: Expr_Array( + items: array( + 0: null + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + 2: null + 3: null + 4: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + 5: null + ) + ) + expr: Expr_Variable( + name: foo + ) + ) + 2: Expr_Assign( + var: Expr_Array( + items: array( + 0: null + 1: Expr_ArrayItem( + key: null + value: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + ) + ) + byRef: false + ) + ) + ) + byRef: false + ) + 2: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + ) + ) + expr: Expr_Variable( + name: bar + ) + ) + 3: Expr_Assign( + var: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Expr_Variable( + name: b + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: Scalar_String( + value: b + ) + value: Expr_Variable( + name: a + ) + byRef: false + ) + ) + ) + expr: Expr_Variable( + name: baz + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assign.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assign.test new file mode 100644 index 0000000..1d6b187 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assign.test @@ -0,0 +1,301 @@ +Assignments +----- +>= $b; +$a **= $b; + +// chained assign +$a = $b *= $c **= $d; + +// by ref assign +$a =& $b; + +// list() assign +list($a) = $b; +list($a, , $b) = $c; +list($a, list(, $c), $d) = $e; + +// inc/dec +++$a; +$a++; +--$a; +$a--; +----- +array( + 0: Expr_Assign( + var: Expr_Variable( + name: a + comments: array( + 0: // simple assign + ) + ) + expr: Expr_Variable( + name: b + ) + comments: array( + 0: // simple assign + ) + ) + 1: Expr_AssignOp_BitwiseAnd( + var: Expr_Variable( + name: a + comments: array( + 0: // combined assign + ) + ) + expr: Expr_Variable( + name: b + ) + comments: array( + 0: // combined assign + ) + ) + 2: Expr_AssignOp_BitwiseOr( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 3: Expr_AssignOp_BitwiseXor( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 4: Expr_AssignOp_Concat( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 5: Expr_AssignOp_Div( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 6: Expr_AssignOp_Minus( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 7: Expr_AssignOp_Mod( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 8: Expr_AssignOp_Mul( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 9: Expr_AssignOp_Plus( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 10: Expr_AssignOp_ShiftLeft( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 11: Expr_AssignOp_ShiftRight( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 12: Expr_AssignOp_Pow( + var: Expr_Variable( + name: a + ) + expr: Expr_Variable( + name: b + ) + ) + 13: Expr_Assign( + var: Expr_Variable( + name: a + comments: array( + 0: // chained assign + ) + ) + expr: Expr_AssignOp_Mul( + var: Expr_Variable( + name: b + ) + expr: Expr_AssignOp_Pow( + var: Expr_Variable( + name: c + ) + expr: Expr_Variable( + name: d + ) + ) + ) + comments: array( + 0: // chained assign + ) + ) + 14: Expr_AssignRef( + var: Expr_Variable( + name: a + comments: array( + 0: // by ref assign + ) + ) + expr: Expr_Variable( + name: b + ) + comments: array( + 0: // by ref assign + ) + ) + 15: Expr_Assign( + var: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + ) + comments: array( + 0: // list() assign + ) + ) + expr: Expr_Variable( + name: b + ) + comments: array( + 0: // list() assign + ) + ) + 16: Expr_Assign( + var: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + 1: null + 2: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + ) + ) + expr: Expr_Variable( + name: c + ) + ) + 17: Expr_Assign( + var: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Expr_List( + items: array( + 0: null + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: c + ) + byRef: false + ) + ) + ) + byRef: false + ) + 2: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: d + ) + byRef: false + ) + ) + ) + expr: Expr_Variable( + name: e + ) + ) + 18: Expr_PreInc( + var: Expr_Variable( + name: a + ) + comments: array( + 0: // inc/dec + ) + ) + 19: Expr_PostInc( + var: Expr_Variable( + name: a + ) + ) + 20: Expr_PreDec( + var: Expr_Variable( + name: a + ) + ) + 21: Expr_PostDec( + var: Expr_Variable( + name: a + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assignNewByRef.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assignNewByRef.test new file mode 100644 index 0000000..10e1317 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/assignNewByRef.test @@ -0,0 +1,39 @@ +Assigning new by reference (PHP 5 only) +----- + $b; +$a >= $b; +$a == $b; +$a === $b; +$a != $b; +$a !== $b; +$a <=> $b; +$a instanceof B; +$a instanceof $b; +----- +array( + 0: Expr_BinaryOp_Smaller( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 1: Expr_BinaryOp_SmallerOrEqual( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 2: Expr_BinaryOp_Greater( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 3: Expr_BinaryOp_GreaterOrEqual( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 4: Expr_BinaryOp_Equal( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 5: Expr_BinaryOp_Identical( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 6: Expr_BinaryOp_NotEqual( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 7: Expr_BinaryOp_NotIdentical( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 8: Expr_BinaryOp_Spaceship( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 9: Expr_Instanceof( + expr: Expr_Variable( + name: a + ) + class: Name( + parts: array( + 0: B + ) + ) + ) + 10: Expr_Instanceof( + expr: Expr_Variable( + name: a + ) + class: Expr_Variable( + name: b + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/constant_expr.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/constant_expr.test new file mode 100644 index 0000000..3e7a23e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/constant_expr.test @@ -0,0 +1,621 @@ +Expressions in static scalar context +----- + 0; +const T_20 = 1 >= 0; +const T_21 = 1 === 1; +const T_22 = 1 !== 1; +const T_23 = 0 != "0"; +const T_24 = 1 == "1"; +const T_25 = 1 + 2 * 3; +const T_26 = "1" + 2 + "3"; +const T_27 = 2 ** 3; +const T_28 = [1, 2, 3][1]; +const T_29 = 12 - 13; +const T_30 = 12 ^ 13; +const T_31 = 12 & 13; +const T_32 = 12 | 13; +const T_33 = 12 % 3; +const T_34 = 100 >> 4; +const T_35 = !false; +----- +array( + 0: Stmt_Const( + consts: array( + 0: Const( + name: T_1 + value: Expr_BinaryOp_ShiftLeft( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 1: Stmt_Const( + consts: array( + 0: Const( + name: T_2 + value: Expr_BinaryOp_Div( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 2 + ) + ) + ) + ) + ) + 2: Stmt_Const( + consts: array( + 0: Const( + name: T_3 + value: Expr_BinaryOp_Plus( + left: Scalar_DNumber( + value: 1.5 + ) + right: Scalar_DNumber( + value: 1.5 + ) + ) + ) + ) + ) + 3: Stmt_Const( + consts: array( + 0: Const( + name: T_4 + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: foo + ) + right: Scalar_String( + value: bar + ) + ) + ) + ) + ) + 4: Stmt_Const( + consts: array( + 0: Const( + name: T_5 + value: Expr_BinaryOp_Mul( + left: Expr_BinaryOp_Plus( + left: Scalar_DNumber( + value: 1.5 + ) + right: Scalar_DNumber( + value: 1.5 + ) + ) + right: Scalar_LNumber( + value: 2 + ) + ) + ) + ) + ) + 5: Stmt_Const( + consts: array( + 0: Const( + name: T_6 + value: Expr_BinaryOp_Concat( + left: Expr_BinaryOp_Concat( + left: Expr_BinaryOp_Concat( + left: Scalar_String( + value: foo + ) + right: Scalar_LNumber( + value: 2 + ) + ) + right: Scalar_LNumber( + value: 3 + ) + ) + right: Scalar_DNumber( + value: 4 + ) + ) + ) + ) + ) + 6: Stmt_Const( + consts: array( + 0: Const( + name: T_7 + value: Scalar_MagicConst_Line( + ) + ) + ) + ) + 7: Stmt_Const( + consts: array( + 0: Const( + name: T_8 + value: Scalar_String( + value: This is a test string + ) + ) + ) + ) + 8: Stmt_Const( + consts: array( + 0: Const( + name: T_9 + value: Expr_BitwiseNot( + expr: Expr_UnaryMinus( + expr: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + ) + 9: Stmt_Const( + consts: array( + 0: Const( + name: T_10 + value: Expr_BinaryOp_Plus( + left: Expr_Ternary( + cond: Expr_UnaryMinus( + expr: Scalar_LNumber( + value: 1 + ) + ) + if: null + else: Scalar_LNumber( + value: 1 + ) + ) + right: Expr_Ternary( + cond: Scalar_LNumber( + value: 0 + ) + if: Scalar_LNumber( + value: 2 + ) + else: Scalar_LNumber( + value: 3 + ) + ) + ) + ) + ) + ) + 10: Stmt_Const( + consts: array( + 0: Const( + name: T_11 + value: Expr_BinaryOp_BooleanAnd( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 11: Stmt_Const( + consts: array( + 0: Const( + name: T_12 + value: Expr_BinaryOp_LogicalAnd( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 12: Stmt_Const( + consts: array( + 0: Const( + name: T_13 + value: Expr_BinaryOp_BooleanOr( + left: Scalar_LNumber( + value: 0 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 13: Stmt_Const( + consts: array( + 0: Const( + name: T_14 + value: Expr_BinaryOp_LogicalOr( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 14: Stmt_Const( + consts: array( + 0: Const( + name: T_15 + value: Expr_BinaryOp_LogicalXor( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 15: Stmt_Const( + consts: array( + 0: Const( + name: T_16 + value: Expr_BinaryOp_LogicalXor( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 16: Stmt_Const( + consts: array( + 0: Const( + name: T_17 + value: Expr_BinaryOp_Smaller( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 17: Stmt_Const( + consts: array( + 0: Const( + name: T_18 + value: Expr_BinaryOp_SmallerOrEqual( + left: Scalar_LNumber( + value: 0 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 18: Stmt_Const( + consts: array( + 0: Const( + name: T_19 + value: Expr_BinaryOp_Greater( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 19: Stmt_Const( + consts: array( + 0: Const( + name: T_20 + value: Expr_BinaryOp_GreaterOrEqual( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + ) + 20: Stmt_Const( + consts: array( + 0: Const( + name: T_21 + value: Expr_BinaryOp_Identical( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 21: Stmt_Const( + consts: array( + 0: Const( + name: T_22 + value: Expr_BinaryOp_NotIdentical( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 22: Stmt_Const( + consts: array( + 0: Const( + name: T_23 + value: Expr_BinaryOp_NotEqual( + left: Scalar_LNumber( + value: 0 + ) + right: Scalar_String( + value: 0 + ) + ) + ) + ) + ) + 23: Stmt_Const( + consts: array( + 0: Const( + name: T_24 + value: Expr_BinaryOp_Equal( + left: Scalar_LNumber( + value: 1 + ) + right: Scalar_String( + value: 1 + ) + ) + ) + ) + ) + 24: Stmt_Const( + consts: array( + 0: Const( + name: T_25 + value: Expr_BinaryOp_Plus( + left: Scalar_LNumber( + value: 1 + ) + right: Expr_BinaryOp_Mul( + left: Scalar_LNumber( + value: 2 + ) + right: Scalar_LNumber( + value: 3 + ) + ) + ) + ) + ) + ) + 25: Stmt_Const( + consts: array( + 0: Const( + name: T_26 + value: Expr_BinaryOp_Plus( + left: Expr_BinaryOp_Plus( + left: Scalar_String( + value: 1 + ) + right: Scalar_LNumber( + value: 2 + ) + ) + right: Scalar_String( + value: 3 + ) + ) + ) + ) + ) + 26: Stmt_Const( + consts: array( + 0: Const( + name: T_27 + value: Expr_BinaryOp_Pow( + left: Scalar_LNumber( + value: 2 + ) + right: Scalar_LNumber( + value: 3 + ) + ) + ) + ) + ) + 27: Stmt_Const( + consts: array( + 0: Const( + name: T_28 + value: Expr_ArrayDimFetch( + var: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 1 + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 2 + ) + byRef: false + ) + 2: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 3 + ) + byRef: false + ) + ) + ) + dim: Scalar_LNumber( + value: 1 + ) + ) + ) + ) + ) + 28: Stmt_Const( + consts: array( + 0: Const( + name: T_29 + value: Expr_BinaryOp_Minus( + left: Scalar_LNumber( + value: 12 + ) + right: Scalar_LNumber( + value: 13 + ) + ) + ) + ) + ) + 29: Stmt_Const( + consts: array( + 0: Const( + name: T_30 + value: Expr_BinaryOp_BitwiseXor( + left: Scalar_LNumber( + value: 12 + ) + right: Scalar_LNumber( + value: 13 + ) + ) + ) + ) + ) + 30: Stmt_Const( + consts: array( + 0: Const( + name: T_31 + value: Expr_BinaryOp_BitwiseAnd( + left: Scalar_LNumber( + value: 12 + ) + right: Scalar_LNumber( + value: 13 + ) + ) + ) + ) + ) + 31: Stmt_Const( + consts: array( + 0: Const( + name: T_32 + value: Expr_BinaryOp_BitwiseOr( + left: Scalar_LNumber( + value: 12 + ) + right: Scalar_LNumber( + value: 13 + ) + ) + ) + ) + ) + 32: Stmt_Const( + consts: array( + 0: Const( + name: T_33 + value: Expr_BinaryOp_Mod( + left: Scalar_LNumber( + value: 12 + ) + right: Scalar_LNumber( + value: 3 + ) + ) + ) + ) + ) + 33: Stmt_Const( + consts: array( + 0: Const( + name: T_34 + value: Expr_BinaryOp_ShiftRight( + left: Scalar_LNumber( + value: 100 + ) + right: Scalar_LNumber( + value: 4 + ) + ) + ) + ) + ) + 34: Stmt_Const( + consts: array( + 0: Const( + name: T_35 + value: Expr_BooleanNot( + expr: Expr_ConstFetch( + name: Name( + parts: array( + 0: false + ) + ) + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/errorSuppress.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/errorSuppress.test new file mode 100644 index 0000000..ce3fce9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/errorSuppress.test @@ -0,0 +1,12 @@ +Error suppression +----- +b['c'](); + +// array dereferencing +a()['b']; +----- +array( + 0: Expr_FuncCall( + name: Name( + parts: array( + 0: a + ) + comments: array( + 0: // function name variations + ) + ) + args: array( + ) + comments: array( + 0: // function name variations + ) + ) + 1: Expr_FuncCall( + name: Expr_Variable( + name: a + ) + args: array( + ) + ) + 2: Expr_FuncCall( + name: Expr_Variable( + name: Scalar_String( + value: a + ) + ) + args: array( + ) + ) + 3: Expr_FuncCall( + name: Expr_Variable( + name: Expr_Variable( + name: a + ) + ) + args: array( + ) + ) + 4: Expr_FuncCall( + name: Expr_Variable( + name: Expr_Variable( + name: Expr_Variable( + name: a + ) + ) + ) + args: array( + ) + ) + 5: Expr_FuncCall( + name: Expr_ArrayDimFetch( + var: Expr_Variable( + name: a + ) + dim: Scalar_String( + value: b + ) + ) + args: array( + ) + ) + 6: Expr_FuncCall( + name: Expr_ArrayDimFetch( + var: Expr_Variable( + name: a + ) + dim: Scalar_String( + value: b + ) + ) + args: array( + ) + ) + 7: Expr_FuncCall( + name: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + dim: Scalar_String( + value: c + ) + ) + args: array( + ) + ) + 8: Expr_ArrayDimFetch( + var: Expr_FuncCall( + name: Name( + parts: array( + 0: a + ) + comments: array( + 0: // array dereferencing + ) + ) + args: array( + ) + comments: array( + 0: // array dereferencing + ) + ) + dim: Scalar_String( + value: b + ) + comments: array( + 0: // array dereferencing + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/newDeref.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/newDeref.test new file mode 100644 index 0000000..5e36ff8 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/newDeref.test @@ -0,0 +1,70 @@ +New expression dereferencing +----- +b; +(new A)->b(); +(new A)['b']; +(new A)['b']['c']; +----- +array( + 0: Expr_PropertyFetch( + var: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) + name: b + ) + 1: Expr_MethodCall( + var: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) + name: b + args: array( + ) + ) + 2: Expr_ArrayDimFetch( + var: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) + dim: Scalar_String( + value: b + ) + ) + 3: Expr_ArrayDimFetch( + var: Expr_ArrayDimFetch( + var: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) + dim: Scalar_String( + value: b + ) + ) + dim: Scalar_String( + value: c + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/objectAccess.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/objectAccess.test new file mode 100644 index 0000000..584461b --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/objectAccess.test @@ -0,0 +1,145 @@ +Object access +----- +b; +$a->b['c']; +$a->b{'c'}; + +// method call variations +$a->b(); +$a->{'b'}(); +$a->$b(); +$a->$b['c'](); + +// array dereferencing +$a->b()['c']; +$a->b(){'c'}; // invalid PHP: drop Support? +----- +!!php5 +array( + 0: Expr_PropertyFetch( + var: Expr_Variable( + name: a + comments: array( + 0: // property fetch variations + ) + ) + name: b + comments: array( + 0: // property fetch variations + ) + ) + 1: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + dim: Scalar_String( + value: c + ) + ) + 2: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + dim: Scalar_String( + value: c + ) + ) + 3: Expr_MethodCall( + var: Expr_Variable( + name: a + comments: array( + 0: // method call variations + ) + ) + name: b + args: array( + ) + comments: array( + 0: // method call variations + ) + ) + 4: Expr_MethodCall( + var: Expr_Variable( + name: a + ) + name: Scalar_String( + value: b + ) + args: array( + ) + ) + 5: Expr_MethodCall( + var: Expr_Variable( + name: a + ) + name: Expr_Variable( + name: b + ) + args: array( + ) + ) + 6: Expr_MethodCall( + var: Expr_Variable( + name: a + ) + name: Expr_ArrayDimFetch( + var: Expr_Variable( + name: b + ) + dim: Scalar_String( + value: c + ) + ) + args: array( + ) + ) + 7: Expr_ArrayDimFetch( + var: Expr_MethodCall( + var: Expr_Variable( + name: a + comments: array( + 0: // array dereferencing + ) + ) + name: b + args: array( + ) + comments: array( + 0: // array dereferencing + ) + ) + dim: Scalar_String( + value: c + ) + comments: array( + 0: // array dereferencing + ) + ) + 8: Expr_ArrayDimFetch( + var: Expr_MethodCall( + var: Expr_Variable( + name: a + ) + name: b + args: array( + ) + ) + dim: Scalar_String( + value: c + ) + ) + 9: Stmt_Nop( + comments: array( + 0: // invalid PHP: drop Support? + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/simpleArrayAccess.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/simpleArrayAccess.test new file mode 100644 index 0000000..ea3f9ef --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/fetchAndCall/simpleArrayAccess.test @@ -0,0 +1,62 @@ +Simple array access +----- + $b) = ['a' => 'b']; +list('a' => list($b => $c), 'd' => $e) = $x; +----- +!!php7 +array( + 0: Expr_Assign( + var: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Expr_Variable( + name: b + ) + byRef: false + ) + ) + ) + expr: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Scalar_String( + value: b + ) + byRef: false + ) + ) + ) + ) + 1: Expr_Assign( + var: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: Expr_Variable( + name: b + ) + value: Expr_Variable( + name: c + ) + byRef: false + ) + ) + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: Scalar_String( + value: d + ) + value: Expr_Variable( + name: e + ) + byRef: false + ) + ) + ) + expr: Expr_Variable( + name: x + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/logic.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/logic.test new file mode 100644 index 0000000..b3634e9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/logic.test @@ -0,0 +1,159 @@ +Logical operators +----- +> $b; +$a ** $b; + +// associativity +$a * $b * $c; +$a * ($b * $c); + +// precedence +$a + $b * $c; +($a + $b) * $c; + +// pow is special +$a ** $b ** $c; +($a ** $b) ** $c; +----- +array( + 0: Expr_BitwiseNot( + expr: Expr_Variable( + name: a + ) + comments: array( + 0: // unary ops + ) + ) + 1: Expr_UnaryPlus( + expr: Expr_Variable( + name: a + ) + ) + 2: Expr_UnaryMinus( + expr: Expr_Variable( + name: a + ) + ) + 3: Expr_BinaryOp_BitwiseAnd( + left: Expr_Variable( + name: a + comments: array( + 0: // binary ops + ) + ) + right: Expr_Variable( + name: b + ) + comments: array( + 0: // binary ops + ) + ) + 4: Expr_BinaryOp_BitwiseOr( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 5: Expr_BinaryOp_BitwiseXor( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 6: Expr_BinaryOp_Concat( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 7: Expr_BinaryOp_Div( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 8: Expr_BinaryOp_Minus( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 9: Expr_BinaryOp_Mod( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 10: Expr_BinaryOp_Mul( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 11: Expr_BinaryOp_Plus( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 12: Expr_BinaryOp_ShiftLeft( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 13: Expr_BinaryOp_ShiftRight( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 14: Expr_BinaryOp_Pow( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + 15: Expr_BinaryOp_Mul( + left: Expr_BinaryOp_Mul( + left: Expr_Variable( + name: a + comments: array( + 0: // associativity + ) + ) + right: Expr_Variable( + name: b + ) + comments: array( + 0: // associativity + ) + ) + right: Expr_Variable( + name: c + ) + comments: array( + 0: // associativity + ) + ) + 16: Expr_BinaryOp_Mul( + left: Expr_Variable( + name: a + ) + right: Expr_BinaryOp_Mul( + left: Expr_Variable( + name: b + ) + right: Expr_Variable( + name: c + ) + ) + ) + 17: Expr_BinaryOp_Plus( + left: Expr_Variable( + name: a + comments: array( + 0: // precedence + ) + ) + right: Expr_BinaryOp_Mul( + left: Expr_Variable( + name: b + ) + right: Expr_Variable( + name: c + ) + ) + comments: array( + 0: // precedence + ) + ) + 18: Expr_BinaryOp_Mul( + left: Expr_BinaryOp_Plus( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + right: Expr_Variable( + name: c + ) + ) + 19: Expr_BinaryOp_Pow( + left: Expr_Variable( + name: a + comments: array( + 0: // pow is special + ) + ) + right: Expr_BinaryOp_Pow( + left: Expr_Variable( + name: b + ) + right: Expr_Variable( + name: c + ) + ) + comments: array( + 0: // pow is special + ) + ) + 20: Expr_BinaryOp_Pow( + left: Expr_BinaryOp_Pow( + left: Expr_Variable( + name: a + ) + right: Expr_Variable( + name: b + ) + ) + right: Expr_Variable( + name: c + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/new.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/new.test new file mode 100644 index 0000000..a132bbb --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/new.test @@ -0,0 +1,146 @@ +New +----- +b(); +new $a->b->c(); +new $a->b['c'](); +new $a->b{'c'}(); + +// test regression introduces by new dereferencing syntax +(new A); +----- +array( + 0: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) + 1: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + 0: Arg( + value: Expr_Variable( + name: b + ) + byRef: false + unpack: false + ) + ) + ) + 2: Expr_New( + class: Expr_Variable( + name: a + ) + args: array( + ) + comments: array( + 0: // class name variations + ) + ) + 3: Expr_New( + class: Expr_ArrayDimFetch( + var: Expr_Variable( + name: a + ) + dim: Scalar_String( + value: b + ) + ) + args: array( + ) + ) + 4: Expr_New( + class: Expr_StaticPropertyFetch( + class: Name( + parts: array( + 0: A + ) + ) + name: b + ) + args: array( + ) + ) + 5: Expr_New( + class: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + args: array( + ) + comments: array( + 0: // DNCR object access + ) + ) + 6: Expr_New( + class: Expr_PropertyFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + name: c + ) + args: array( + ) + ) + 7: Expr_New( + class: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + dim: Scalar_String( + value: c + ) + ) + args: array( + ) + ) + 8: Expr_New( + class: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Variable( + name: a + ) + name: b + ) + dim: Scalar_String( + value: c + ) + ) + args: array( + ) + ) + 9: Expr_New( + class: Name( + parts: array( + 0: A + ) + ) + args: array( + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/newWithoutClass.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/newWithoutClass.test new file mode 100644 index 0000000..ca7f498 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/newWithoutClass.test @@ -0,0 +1,23 @@ +New without a class +----- +bar; +----- +!!php7 +Syntax error, unexpected T_OBJECT_OPERATOR, expecting ';' from 2:13 to 2:14 +array( + 0: Stmt_Global( + vars: array( + 0: Expr_Variable( + name: Expr_Variable( + name: foo + ) + ) + ) + ) + 1: Expr_ConstFetch( + name: Name( + parts: array( + 0: bar + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/indirectCall.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/indirectCall.test new file mode 100644 index 0000000..bb3e7fb --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/indirectCall.test @@ -0,0 +1,481 @@ +UVS indirect calls +----- + 'b']->a); +isset("str"->a); +----- +!!php7 +array( + 0: Expr_Isset( + vars: array( + 0: Expr_ArrayDimFetch( + var: Expr_BinaryOp_Plus( + left: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 0 + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 1 + ) + byRef: false + ) + ) + ) + right: Expr_Array( + items: array( + ) + ) + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + 1: Expr_Isset( + vars: array( + 0: Expr_PropertyFetch( + var: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: Scalar_String( + value: a + ) + value: Scalar_String( + value: b + ) + byRef: false + ) + ) + ) + name: a + ) + ) + ) + 2: Expr_Isset( + vars: array( + 0: Expr_PropertyFetch( + var: Scalar_String( + value: str + ) + name: a + ) + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/misc.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/misc.test new file mode 100644 index 0000000..2c5ba90 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/misc.test @@ -0,0 +1,109 @@ +Uniform variable syntax in PHP 7 (misc) +----- +length(); +(clone $obj)->b[0](1); +[0, 1][0] = 1; +----- +!!php7 +array( + 0: Expr_ArrayDimFetch( + var: Expr_ClassConstFetch( + class: Name( + parts: array( + 0: A + ) + ) + name: A + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + 1: Expr_ArrayDimFetch( + var: Expr_ArrayDimFetch( + var: Expr_ArrayDimFetch( + var: Expr_ClassConstFetch( + class: Name( + parts: array( + 0: A + ) + ) + name: A + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + dim: Scalar_LNumber( + value: 1 + ) + ) + dim: Scalar_LNumber( + value: 2 + ) + ) + 2: Expr_MethodCall( + var: Scalar_String( + value: string + ) + name: length + args: array( + ) + ) + 3: Expr_FuncCall( + name: Expr_ArrayDimFetch( + var: Expr_PropertyFetch( + var: Expr_Clone( + expr: Expr_Variable( + name: obj + ) + ) + name: b + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + args: array( + 0: Arg( + value: Scalar_LNumber( + value: 1 + ) + byRef: false + unpack: false + ) + ) + ) + 4: Expr_Assign( + var: Expr_ArrayDimFetch( + var: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 0 + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Scalar_LNumber( + value: 1 + ) + byRef: false + ) + ) + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + expr: Scalar_LNumber( + value: 1 + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/new.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/new.test new file mode 100644 index 0000000..e5f92f9 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/new.test @@ -0,0 +1,95 @@ +UVS new expressions +----- +className; +new Test::$className; +new $test::$className; +new $weird[0]->foo::$className; +----- +!!php7 +array( + 0: Expr_New( + class: Expr_Variable( + name: className + ) + args: array( + ) + ) + 1: Expr_New( + class: Expr_ArrayDimFetch( + var: Expr_Variable( + name: array + ) + dim: Scalar_String( + value: className + ) + ) + args: array( + ) + ) + 2: Expr_New( + class: Expr_ArrayDimFetch( + var: Expr_Variable( + name: array + ) + dim: Scalar_String( + value: className + ) + ) + args: array( + ) + ) + 3: Expr_New( + class: Expr_PropertyFetch( + var: Expr_Variable( + name: obj + ) + name: className + ) + args: array( + ) + ) + 4: Expr_New( + class: Expr_StaticPropertyFetch( + class: Name( + parts: array( + 0: Test + ) + ) + name: className + ) + args: array( + ) + ) + 5: Expr_New( + class: Expr_StaticPropertyFetch( + class: Expr_Variable( + name: test + ) + name: className + ) + args: array( + ) + ) + 6: Expr_New( + class: Expr_StaticPropertyFetch( + class: Expr_PropertyFetch( + var: Expr_ArrayDimFetch( + var: Expr_Variable( + name: weird + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + name: foo + ) + name: className + ) + args: array( + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/staticProperty.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/staticProperty.test new file mode 100644 index 0000000..5fadfc4 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/expr/uvs/staticProperty.test @@ -0,0 +1,93 @@ +UVS static access +----- +c test +EOS; + +b<<B"; +"$A[B]"; +"$A[0]"; +"$A[1234]"; +"$A[9223372036854775808]"; +"$A[000]"; +"$A[0x0]"; +"$A[0b0]"; +"$A[$B]"; +"{$A}"; +"{$A['B']}"; +"${A}"; +"${A['B']}"; +"${$A}"; +"\{$A}"; +"\{ $A }"; +"\\{$A}"; +"\\{ $A }"; +"{$$A}[B]"; +"$$A[B]"; +"A $B C"; +b"$A"; +B"$A"; +----- +array( + 0: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: A + ) + ) + ) + 1: Scalar_Encapsed( + parts: array( + 0: Expr_PropertyFetch( + var: Expr_Variable( + name: A + ) + name: B + ) + ) + ) + 2: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: B + ) + ) + ) + ) + 3: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_LNumber( + value: 0 + ) + ) + ) + ) + 4: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_LNumber( + value: 1234 + ) + ) + ) + ) + 5: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: 9223372036854775808 + ) + ) + ) + ) + 6: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: 000 + ) + ) + ) + ) + 7: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: 0x0 + ) + ) + ) + ) + 8: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: 0b0 + ) + ) + ) + ) + 9: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Expr_Variable( + name: B + ) + ) + ) + ) + 10: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: A + ) + ) + ) + 11: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: B + ) + ) + ) + ) + 12: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: A + ) + ) + ) + 13: Scalar_Encapsed( + parts: array( + 0: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: B + ) + ) + ) + ) + 14: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: Expr_Variable( + name: A + ) + ) + ) + ) + 15: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: \{ + ) + 1: Expr_Variable( + name: A + ) + 2: Scalar_EncapsedStringPart( + value: } + ) + ) + ) + 16: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: \{ + ) + 1: Expr_Variable( + name: A + ) + 2: Scalar_EncapsedStringPart( + value: } + ) + ) + ) + 17: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: \ + ) + 1: Expr_Variable( + name: A + ) + ) + ) + 18: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: \{ + ) + 1: Expr_Variable( + name: A + ) + 2: Scalar_EncapsedStringPart( + value: } + ) + ) + ) + 19: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: Expr_Variable( + name: A + ) + ) + 1: Scalar_EncapsedStringPart( + value: [B] + ) + ) + ) + 20: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: $ + ) + 1: Expr_ArrayDimFetch( + var: Expr_Variable( + name: A + ) + dim: Scalar_String( + value: B + ) + ) + ) + ) + 21: Scalar_Encapsed( + parts: array( + 0: Scalar_EncapsedStringPart( + value: A + ) + 1: Expr_Variable( + name: B + ) + 2: Scalar_EncapsedStringPart( + value: C + ) + ) + ) + 22: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: A + ) + ) + ) + 23: Scalar_Encapsed( + parts: array( + 0: Expr_Variable( + name: A + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/float.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/float.test new file mode 100644 index 0000000..a16028e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/float.test @@ -0,0 +1,74 @@ +Different float syntaxes +----- + float overflows +// (all are actually the same number, just in different representations) +18446744073709551615; +0xFFFFFFFFFFFFFFFF; +01777777777777777777777; +0177777777777777777777787; +0b1111111111111111111111111111111111111111111111111111111111111111; +----- +array( + 0: Scalar_DNumber( + value: 0 + ) + 1: Scalar_DNumber( + value: 0 + ) + 2: Scalar_DNumber( + value: 0 + ) + 3: Scalar_DNumber( + value: 0 + ) + 4: Scalar_DNumber( + value: 0 + ) + 5: Scalar_DNumber( + value: 0 + ) + 6: Scalar_DNumber( + value: 0 + ) + 7: Scalar_DNumber( + value: 302000000000 + ) + 8: Scalar_DNumber( + value: 3.002E+102 + ) + 9: Scalar_DNumber( + value: INF + ) + 10: Scalar_DNumber( + value: 1.844674407371E+19 + comments: array( + 0: // various integer -> float overflows + 1: // (all are actually the same number, just in different representations) + ) + ) + 11: Scalar_DNumber( + value: 1.844674407371E+19 + ) + 12: Scalar_DNumber( + value: 1.844674407371E+19 + ) + 13: Scalar_DNumber( + value: 1.844674407371E+19 + ) + 14: Scalar_DNumber( + value: 1.844674407371E+19 + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/int.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/int.test new file mode 100644 index 0000000..5a21267 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/scalar/int.test @@ -0,0 +1,43 @@ +Different integer syntaxes +----- +array(); +$t->public(); + +Test::list(); +Test::protected(); + +$t->class; +$t->private; + +Test::TRAIT; +Test::FINAL; + +class Foo { + use TraitA, TraitB { + TraitA::catch insteadof namespace\TraitB; + TraitA::list as foreach; + TraitB::throw as protected public; + TraitB::self as protected; + exit as die; + \TraitC::exit as bye; + namespace\TraitC::exit as byebye; + TraitA:: + // + /** doc comment */ + # + catch /* comment */ + // comment + # comment + insteadof TraitB; + } +} +----- +array( + 0: Stmt_Class( + flags: 0 + name: Test + extends: null + implements: array( + ) + stmts: array( + 0: Stmt_ClassMethod( + flags: 0 + byRef: false + name: array + params: array( + ) + returnType: null + stmts: array( + ) + ) + 1: Stmt_ClassMethod( + flags: 0 + byRef: false + name: public + params: array( + ) + returnType: null + stmts: array( + ) + ) + 2: Stmt_ClassMethod( + flags: MODIFIER_STATIC (8) + byRef: false + name: list + params: array( + ) + returnType: null + stmts: array( + ) + ) + 3: Stmt_ClassMethod( + flags: MODIFIER_STATIC (8) + byRef: false + name: protected + params: array( + ) + returnType: null + stmts: array( + ) + ) + 4: Stmt_Property( + flags: MODIFIER_PUBLIC (1) + props: array( + 0: Stmt_PropertyProperty( + name: class + default: null + ) + ) + ) + 5: Stmt_Property( + flags: MODIFIER_PUBLIC (1) + props: array( + 0: Stmt_PropertyProperty( + name: private + default: null + ) + ) + ) + 6: Stmt_ClassConst( + flags: 0 + consts: array( + 0: Const( + name: TRAIT + value: Scalar_LNumber( + value: 3 + ) + ) + 1: Const( + name: FINAL + value: Scalar_LNumber( + value: 4 + ) + ) + ) + ) + 7: Stmt_ClassConst( + flags: 0 + consts: array( + 0: Const( + name: __CLASS__ + value: Scalar_LNumber( + value: 1 + ) + ) + 1: Const( + name: __TRAIT__ + value: Scalar_LNumber( + value: 2 + ) + ) + 2: Const( + name: __FUNCTION__ + value: Scalar_LNumber( + value: 3 + ) + ) + 3: Const( + name: __METHOD__ + value: Scalar_LNumber( + value: 4 + ) + ) + 4: Const( + name: __LINE__ + value: Scalar_LNumber( + value: 5 + ) + ) + 5: Const( + name: __FILE__ + value: Scalar_LNumber( + value: 6 + ) + ) + 6: Const( + name: __DIR__ + value: Scalar_LNumber( + value: 7 + ) + ) + 7: Const( + name: __NAMESPACE__ + value: Scalar_LNumber( + value: 8 + ) + ) + ) + ) + ) + ) + 1: Expr_Assign( + var: Expr_Variable( + name: t + ) + expr: Expr_New( + class: Name( + parts: array( + 0: Test + ) + ) + args: array( + ) + ) + ) + 2: Expr_MethodCall( + var: Expr_Variable( + name: t + ) + name: array + args: array( + ) + ) + 3: Expr_MethodCall( + var: Expr_Variable( + name: t + ) + name: public + args: array( + ) + ) + 4: Expr_StaticCall( + class: Name( + parts: array( + 0: Test + ) + ) + name: list + args: array( + ) + ) + 5: Expr_StaticCall( + class: Name( + parts: array( + 0: Test + ) + ) + name: protected + args: array( + ) + ) + 6: Expr_PropertyFetch( + var: Expr_Variable( + name: t + ) + name: class + ) + 7: Expr_PropertyFetch( + var: Expr_Variable( + name: t + ) + name: private + ) + 8: Expr_ClassConstFetch( + class: Name( + parts: array( + 0: Test + ) + ) + name: TRAIT + ) + 9: Expr_ClassConstFetch( + class: Name( + parts: array( + 0: Test + ) + ) + name: FINAL + ) + 10: Stmt_Class( + flags: 0 + name: Foo + extends: null + implements: array( + ) + stmts: array( + 0: Stmt_TraitUse( + traits: array( + 0: Name( + parts: array( + 0: TraitA + ) + ) + 1: Name( + parts: array( + 0: TraitB + ) + ) + ) + adaptations: array( + 0: Stmt_TraitUseAdaptation_Precedence( + trait: Name( + parts: array( + 0: TraitA + ) + ) + method: catch + insteadof: array( + 0: Name_Relative( + parts: array( + 0: TraitB + ) + ) + ) + ) + 1: Stmt_TraitUseAdaptation_Alias( + trait: Name( + parts: array( + 0: TraitA + ) + ) + method: list + newModifier: null + newName: foreach + ) + 2: Stmt_TraitUseAdaptation_Alias( + trait: Name( + parts: array( + 0: TraitB + ) + ) + method: throw + newModifier: MODIFIER_PROTECTED (2) + newName: public + ) + 3: Stmt_TraitUseAdaptation_Alias( + trait: Name( + parts: array( + 0: TraitB + ) + ) + method: self + newModifier: MODIFIER_PROTECTED (2) + newName: null + ) + 4: Stmt_TraitUseAdaptation_Alias( + trait: null + method: exit + newModifier: null + newName: die + ) + 5: Stmt_TraitUseAdaptation_Alias( + trait: Name_FullyQualified( + parts: array( + 0: TraitC + ) + ) + method: exit + newModifier: null + newName: bye + ) + 6: Stmt_TraitUseAdaptation_Alias( + trait: Name_Relative( + parts: array( + 0: TraitC + ) + ) + method: exit + newModifier: null + newName: byebye + ) + 7: Stmt_TraitUseAdaptation_Precedence( + trait: Name( + parts: array( + 0: TraitA + ) + ) + method: catch + insteadof: array( + 0: Name( + parts: array( + 0: TraitB + ) + ) + ) + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/blocklessStatement.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/blocklessStatement.test new file mode 100644 index 0000000..ae83dab --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/blocklessStatement.test @@ -0,0 +1,112 @@ +Blockless statements for if/for/etc +----- + 'baz'] +) {} +----- +array( + 0: Stmt_Function( + byRef: false + name: a + params: array( + 0: Param( + type: null + byRef: false + variadic: false + name: b + default: Expr_ConstFetch( + name: Name( + parts: array( + 0: null + ) + ) + ) + ) + 1: Param( + type: null + byRef: false + variadic: false + name: c + default: Scalar_String( + value: foo + ) + ) + 2: Param( + type: null + byRef: false + variadic: false + name: d + default: Expr_ClassConstFetch( + class: Name( + parts: array( + 0: A + ) + ) + name: B + ) + ) + 3: Param( + type: null + byRef: false + variadic: false + name: f + default: Expr_UnaryPlus( + expr: Scalar_LNumber( + value: 1 + ) + ) + ) + 4: Param( + type: null + byRef: false + variadic: false + name: g + default: Expr_UnaryMinus( + expr: Scalar_DNumber( + value: 1 + ) + ) + ) + 5: Param( + type: null + byRef: false + variadic: false + name: h + default: Expr_Array( + items: array( + ) + ) + ) + 6: Param( + type: null + byRef: false + variadic: false + name: i + default: Expr_Array( + items: array( + ) + ) + ) + 7: Param( + type: null + byRef: false + variadic: false + name: j + default: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: foo + ) + byRef: false + ) + ) + ) + ) + 8: Param( + type: null + byRef: false + variadic: false + name: k + default: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Scalar_String( + value: foo + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: Scalar_String( + value: bar + ) + value: Scalar_String( + value: baz + ) + byRef: false + ) + ) + ) + ) + ) + returnType: null + stmts: array( + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/function/nullableTypes.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/function/nullableTypes.test new file mode 100644 index 0000000..d96df4f --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/function/nullableTypes.test @@ -0,0 +1,47 @@ +Nullable types +----- + $value; + + // expressions + $data = yield; + $data = (yield $value); + $data = (yield $key => $value); + + // yield in language constructs with their own parentheses + if (yield $foo); elseif (yield $foo); + if (yield $foo): elseif (yield $foo): endif; + while (yield $foo); + do {} while (yield $foo); + switch (yield $foo) {} + die(yield $foo); + + // yield in function calls + func(yield $foo); + $foo->func(yield $foo); + new Foo(yield $foo); + + yield from $foo; + yield from $foo and yield from $bar; + yield from $foo + $bar; +} +----- +array( + 0: Stmt_Function( + byRef: false + name: gen + params: array( + ) + returnType: null + stmts: array( + 0: Expr_Yield( + key: null + value: null + comments: array( + 0: // statements + ) + ) + 1: Expr_Yield( + key: null + value: Expr_Variable( + name: value + ) + ) + 2: Expr_Yield( + key: Expr_Variable( + name: key + ) + value: Expr_Variable( + name: value + ) + ) + 3: Expr_Assign( + var: Expr_Variable( + name: data + comments: array( + 0: // expressions + ) + ) + expr: Expr_Yield( + key: null + value: null + ) + comments: array( + 0: // expressions + ) + ) + 4: Expr_Assign( + var: Expr_Variable( + name: data + ) + expr: Expr_Yield( + key: null + value: Expr_Variable( + name: value + ) + ) + ) + 5: Expr_Assign( + var: Expr_Variable( + name: data + ) + expr: Expr_Yield( + key: Expr_Variable( + name: key + ) + value: Expr_Variable( + name: value + ) + ) + ) + 6: Stmt_If( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + elseifs: array( + 0: Stmt_ElseIf( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + ) + ) + else: null + comments: array( + 0: // yield in language constructs with their own parentheses + ) + ) + 7: Stmt_If( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + elseifs: array( + 0: Stmt_ElseIf( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + ) + ) + else: null + ) + 8: Stmt_While( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + ) + 9: Stmt_Do( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + stmts: array( + ) + ) + 10: Stmt_Switch( + cond: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + cases: array( + ) + ) + 11: Expr_Exit( + expr: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + ) + 12: Expr_FuncCall( + name: Name( + parts: array( + 0: func + ) + comments: array( + 0: // yield in function calls + ) + ) + args: array( + 0: Arg( + value: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + byRef: false + unpack: false + ) + ) + comments: array( + 0: // yield in function calls + ) + ) + 13: Expr_MethodCall( + var: Expr_Variable( + name: foo + ) + name: func + args: array( + 0: Arg( + value: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + byRef: false + unpack: false + ) + ) + ) + 14: Expr_New( + class: Name( + parts: array( + 0: Foo + ) + ) + args: array( + 0: Arg( + value: Expr_Yield( + key: null + value: Expr_Variable( + name: foo + ) + ) + byRef: false + unpack: false + ) + ) + ) + 15: Expr_YieldFrom( + expr: Expr_Variable( + name: foo + ) + ) + 16: Expr_BinaryOp_LogicalAnd( + left: Expr_YieldFrom( + expr: Expr_Variable( + name: foo + ) + ) + right: Expr_YieldFrom( + expr: Expr_Variable( + name: bar + ) + ) + ) + 17: Expr_YieldFrom( + expr: Expr_BinaryOp_Plus( + left: Expr_Variable( + name: foo + ) + right: Expr_Variable( + name: bar + ) + ) + ) + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldPrecedence.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldPrecedence.test new file mode 100644 index 0000000..ff0d4df --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldPrecedence.test @@ -0,0 +1,230 @@ +Yield operator precedence +----- + "a" . "b"; + yield "k" => "a" or die; + var_dump([yield "k" => "a" . "b"]); + yield yield "k1" => yield "k2" => "a" . "b"; + yield yield "k1" => (yield "k2") => "a" . "b"; + var_dump([yield "k1" => yield "k2" => "a" . "b"]); + var_dump([yield "k1" => (yield "k2") => "a" . "b"]); +} +----- +!!php7 +array( + 0: Stmt_Function( + byRef: false + name: gen + params: array( + ) + returnType: null + stmts: array( + 0: Expr_Yield( + key: null + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + 1: Expr_BinaryOp_LogicalOr( + left: Expr_Yield( + key: null + value: Scalar_String( + value: a + ) + ) + right: Expr_Exit( + expr: null + ) + ) + 2: Expr_Yield( + key: Scalar_String( + value: k + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + 3: Expr_BinaryOp_LogicalOr( + left: Expr_Yield( + key: Scalar_String( + value: k + ) + value: Scalar_String( + value: a + ) + ) + right: Expr_Exit( + expr: null + ) + ) + 4: Expr_FuncCall( + name: Name( + parts: array( + 0: var_dump + ) + ) + args: array( + 0: Arg( + value: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Yield( + key: Scalar_String( + value: k + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + byRef: false + ) + ) + ) + byRef: false + unpack: false + ) + ) + ) + 5: Expr_Yield( + key: null + value: Expr_Yield( + key: Scalar_String( + value: k1 + ) + value: Expr_Yield( + key: Scalar_String( + value: k2 + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + ) + ) + 6: Expr_Yield( + key: Expr_Yield( + key: Scalar_String( + value: k1 + ) + value: Expr_Yield( + key: null + value: Scalar_String( + value: k2 + ) + ) + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + 7: Expr_FuncCall( + name: Name( + parts: array( + 0: var_dump + ) + ) + args: array( + 0: Arg( + value: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Yield( + key: Scalar_String( + value: k1 + ) + value: Expr_Yield( + key: Scalar_String( + value: k2 + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + ) + ) + byRef: false + ) + ) + ) + byRef: false + unpack: false + ) + ) + ) + 8: Expr_FuncCall( + name: Name( + parts: array( + 0: var_dump + ) + ) + args: array( + 0: Arg( + value: Expr_Array( + items: array( + 0: Expr_ArrayItem( + key: Expr_Yield( + key: Scalar_String( + value: k1 + ) + value: Expr_Yield( + key: null + value: Scalar_String( + value: k2 + ) + ) + ) + value: Expr_BinaryOp_Concat( + left: Scalar_String( + value: a + ) + right: Scalar_String( + value: b + ) + ) + byRef: false + ) + ) + ) + byRef: false + unpack: false + ) + ) + ) + ) + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldUnaryPrecedence.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldUnaryPrecedence.test new file mode 100644 index 0000000..13f9660 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/generator/yieldUnaryPrecedence.test @@ -0,0 +1,48 @@ +Yield with unary operator argument +----- + +Hallo World! +----- +array( + 0: Expr_Variable( + name: a + ) + 1: Stmt_HaltCompiler( + remaining: Hallo World! + ) +) +----- + +#!/usr/bin/env php +----- +array( + 0: Stmt_InlineHTML( + value: #!/usr/bin/env php + + ) + 1: Stmt_Echo( + exprs: array( + 0: Scalar_String( + value: foobar + ) + ) + ) + 2: Stmt_InlineHTML( + value: #!/usr/bin/env php + ) +) diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/if.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/if.test new file mode 100644 index 0000000..e054c89 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/if.test @@ -0,0 +1,103 @@ +If/Elseif/Else +----- + +B + + $c) {} +foreach ($a as $b => &$c) {} +foreach ($a as list($a, $b)) {} +foreach ($a as $a => list($b, , $c)) {} + +// foreach on expression +foreach (array() as $b) {} + +// alternative syntax +foreach ($a as $b): +endforeach; +----- +array( + 0: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: null + byRef: false + valueVar: Expr_Variable( + name: b + ) + stmts: array( + ) + comments: array( + 0: // foreach on variable + ) + ) + 1: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: null + byRef: true + valueVar: Expr_Variable( + name: b + ) + stmts: array( + ) + ) + 2: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: Expr_Variable( + name: b + ) + byRef: false + valueVar: Expr_Variable( + name: c + ) + stmts: array( + ) + ) + 3: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: Expr_Variable( + name: b + ) + byRef: true + valueVar: Expr_Variable( + name: c + ) + stmts: array( + ) + ) + 4: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: null + byRef: false + valueVar: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: a + ) + byRef: false + ) + 1: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + ) + ) + stmts: array( + ) + ) + 5: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: Expr_Variable( + name: a + ) + byRef: false + valueVar: Expr_List( + items: array( + 0: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: b + ) + byRef: false + ) + 1: null + 2: Expr_ArrayItem( + key: null + value: Expr_Variable( + name: c + ) + byRef: false + ) + ) + ) + stmts: array( + ) + ) + 6: Stmt_Foreach( + expr: Expr_Array( + items: array( + ) + ) + keyVar: null + byRef: false + valueVar: Expr_Variable( + name: b + ) + stmts: array( + ) + comments: array( + 0: // foreach on expression + ) + ) + 7: Stmt_Foreach( + expr: Expr_Variable( + name: a + ) + keyVar: null + byRef: false + valueVar: Expr_Variable( + name: b + ) + stmts: array( + ) + comments: array( + 0: // alternative syntax + ) + ) +) \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/loop/while.test b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/loop/while.test new file mode 100644 index 0000000..65f6b23 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/parser/stmt/loop/while.test @@ -0,0 +1,25 @@ +While loop +----- + +Hi! +----- +array( + 0: Stmt_Declare( + declares: array( + 0: Stmt_DeclareDeclare( + key: A + value: Scalar_String( + value: B + ) + ) + ) + stmts: null + ) + 1: Stmt_Namespace( + name: Name( + parts: array( + 0: B + ) + ) + stmts: array( + ) + ) + 2: Stmt_HaltCompiler( + remaining: Hi! + ) +) +----- +a = $a; + } +}; +----- +new class +{ +}; +new class extends A implements B, C +{ +}; +new class($a) extends A +{ + private $a; + public function __construct($a) + { + $this->a = $a; + } +}; diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/arrayDestructuring.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/arrayDestructuring.test new file mode 100644 index 0000000..bff1999 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/arrayDestructuring.test @@ -0,0 +1,14 @@ +Array destructuring +----- + $b, 'b' => $a] = $baz; +----- +!!php7 +[$a, $b] = [$c, $d]; +[, $a, , , $b, ] = $foo; +[, [[$a]], $b] = $bar; +['a' => $b, 'b' => $a] = $baz; \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/call.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/call.test new file mode 100644 index 0000000..0ec8925 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/call.test @@ -0,0 +1,13 @@ +Calls +----- +d} +STR; + +call( + <<d} +STR; +call(<<> $b; +$a < $b; +$a <= $b; +$a > $b; +$a >= $b; +$a == $b; +$a != $b; +$a <> $b; +$a === $b; +$a !== $b; +$a <=> $b; +$a & $b; +$a ^ $b; +$a | $b; +$a && $b; +$a || $b; +$a ? $b : $c; +$a ?: $c; +$a ?? $c; + +$a = $b; +$a **= $b; +$a *= $b; +$a /= $b; +$a %= $b; +$a += $b; +$a -= $b; +$a .= $b; +$a <<= $b; +$a >>= $b; +$a &= $b; +$a ^= $b; +$a |= $b; +$a =& $b; + +$a and $b; +$a xor $b; +$a or $b; + +$a instanceof Foo; +$a instanceof $b; +----- +$a ** $b; +++$a; +--$a; +$a++; +$a--; +@$a; +~$a; +-$a; ++$a; +(int) $a; +(int) $a; +(double) $a; +(double) $a; +(double) $a; +(string) $a; +(string) $a; +(array) $a; +(object) $a; +(bool) $a; +(bool) $a; +(unset) $a; +$a * $b; +$a / $b; +$a % $b; +$a + $b; +$a - $b; +$a . $b; +$a << $b; +$a >> $b; +$a < $b; +$a <= $b; +$a > $b; +$a >= $b; +$a == $b; +$a != $b; +$a != $b; +$a === $b; +$a !== $b; +$a <=> $b; +$a & $b; +$a ^ $b; +$a | $b; +$a && $b; +$a || $b; +$a ? $b : $c; +$a ?: $c; +$a ?? $c; +$a = $b; +$a **= $b; +$a *= $b; +$a /= $b; +$a %= $b; +$a += $b; +$a -= $b; +$a .= $b; +$a <<= $b; +$a >>= $b; +$a &= $b; +$a ^= $b; +$a |= $b; +$a =& $b; +$a and $b; +$a xor $b; +$a or $b; +$a instanceof Foo; +$a instanceof $b; diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/parentheses.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/parentheses.test new file mode 100644 index 0000000..a49c110 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/parentheses.test @@ -0,0 +1,86 @@ +Pretty printer generates least-parentheses output +----- + 0) > (1 < 0); +++$a + $b; +$a + $b++; + +$a ** $b ** $c; +($a ** $b) ** $c; +-1 ** 2; + +yield from $a and yield from $b; +yield from ($a and yield from $b); + +print ($a and print $b); + +-(-$a); ++(+$a); +-(--$a); ++(++$a); + +// The following will currently add unnecessary parentheses, because the pretty printer is not aware that assignment +// and incdec only work on variables. +!$a = $b; +++$a ** $b; +$a ** $b++; +----- +echo 'abc' . 'cde' . 'fgh'; +echo 'abc' . ('cde' . 'fgh'); +echo 'abc' . 1 + 2 . 'fgh'; +echo 'abc' . (1 + 2) . 'fgh'; +echo 1 * 2 + 3 / 4 % 5 . 6; +echo 1 * (2 + 3) / (4 % (5 . 6)); +$a = $b = $c = $d = $f && true; +($a = $b = $c = $d = $f) && true; +$a = $b = $c = $d = $f and true; +$a = $b = $c = $d = ($f and true); +$a ? $b : $c ? $d : $e ? $f : $g; +$a ? $b : ($c ? $d : ($e ? $f : $g)); +$a ? $b ? $c : $d : $f; +$a ?? $b ?? $c; +($a ?? $b) ?? $c; +$a ?? ($b ? $c : $d); +$a || ($b ?? $c); +(1 > 0) > (1 < 0); +++$a + $b; +$a + $b++; +$a ** $b ** $c; +($a ** $b) ** $c; +-1 ** 2; +yield from $a and yield from $b; +yield from ($a and yield from $b); +print ($a and print $b); +-(-$a); ++(+$a); +-(--$a); ++(++$a); +// The following will currently add unnecessary parentheses, because the pretty printer is not aware that assignment +// and incdec only work on variables. +!($a = $b); +(++$a) ** $b; +$a ** ($b++); diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/shortArraySyntax.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/shortArraySyntax.test new file mode 100644 index 0000000..082c2e0 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/shortArraySyntax.test @@ -0,0 +1,11 @@ +Short array syntax +----- + 'b', 'c' => 'd']; +----- +[]; +array(1, 2, 3); +['a' => 'b', 'c' => 'd']; \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/stringEscaping.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/stringEscaping.test new file mode 100644 index 0000000..02877ad --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/stringEscaping.test @@ -0,0 +1,23 @@ +Escape sequences in double-quoted strings +----- +b)(); +(A::$b)(); +----- +!!php7 +(function () { +})(); +array('a', 'b')()(); +A::$b::$c; +$A::$b[$c](); +$A::{$b[$c]}(); +A::${$b}[$c](); +($a->b)(); +(A::$b)(); diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/variables.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/variables.test new file mode 100644 index 0000000..4e0fa2e --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/variables.test @@ -0,0 +1,73 @@ +Variables +----- +b; +$a->b(); +$a->b($c); +$a->$b(); +$a->{$b}(); +$a->$b[$c](); +$$a->b; +$a[$b]; +$a[$b](); +$$a[$b]; +$a::B; +$a::$b; +$a::b(); +$a::b($c); +$a::$b(); +$a::$b[$c]; +$a::$b[$c]($d); +$a::{$b[$c]}($d); +$a::{$b->c}(); +A::$$b[$c](); +a(); +$a(); +$a()[$b]; +$a->b()[$c]; +$a::$b()[$c]; +(new A)->b; +(new A())->b(); +(new $$a)[$b]; +(new $a->b)->c; + +global $a, $$a, $$a[$b], $$a->b; +----- +!!php5 +$a; +${$a}; +${$a}; +$a->b; +$a->b(); +$a->b($c); +$a->{$b}(); +$a->{$b}(); +$a->{$b[$c]}(); +${$a}->b; +$a[$b]; +$a[$b](); +${$a[$b]}; +$a::B; +$a::$b; +$a::b(); +$a::b($c); +$a::$b(); +$a::$b[$c]; +$a::{$b[$c]}($d); +$a::{$b[$c]}($d); +$a::{$b->c}(); +A::${$b[$c]}(); +a(); +$a(); +$a()[$b]; +$a->b()[$c]; +$a::$b()[$c]; +(new A())->b; +(new A())->b(); +(new ${$a}())[$b]; +(new $a->b())->c; +global $a, ${$a}, ${$a[$b]}, ${$a->b}; diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/yield.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/yield.test new file mode 100644 index 0000000..12ab7de --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/expr/yield.test @@ -0,0 +1,46 @@ +Yield +----- + $b; + $a = yield; + $a = (yield $b); + $a = (yield $b => $c); +} +// TODO Get rid of parens for cases 2 and 3 +----- +function gen() +{ + yield; + (yield $a); + (yield $a => $b); + $a = yield; + $a = (yield $b); + $a = (yield $b => $c); +} +// TODO Get rid of parens for cases 2 and 3 +----- + $c; + yield from $a; + $a = yield from $b; +} +// TODO Get rid of parens for last case +----- +!!php7 +function gen() +{ + $a = (yield $b); + $a = (yield $b => $c); + yield from $a; + $a = (yield from $b); +} +// TODO Get rid of parens for last case \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/inlineHTMLandPHPtest.file-test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/inlineHTMLandPHPtest.file-test new file mode 100644 index 0000000..b33eb52 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/inlineHTMLandPHPtest.file-test @@ -0,0 +1,58 @@ +File containing both inline HTML and PHP +----- +HTML + +HTML +----- + +HTML +----- +HTML + +HTML +----- +HTML + +HTML +----- +HTML + +HTML + +HTML +----- +HTML + +HTML + +HTML +----- +HTMLHTML +----- +HTMLHTML \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyInlineHTML.file-test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyInlineHTML.file-test new file mode 100644 index 0000000..e980719 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyInlineHTML.file-test @@ -0,0 +1,19 @@ +File containing only inline HTML +----- +Hallo World +Foo Bar +Bar Foo +World Hallo +----- +Hallo World +Foo Bar +Bar Foo +World Hallo +----- + + +Test +----- + + +Test \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyPHP.file-test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyPHP.file-test new file mode 100644 index 0000000..9550b10 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/onlyPHP.file-test @@ -0,0 +1,16 @@ +File containing only PHP +----- +a = 'bar'; + echo 'test'; + } + + protected function baz() {} + public function foo() {} + abstract static function bar() {} +} + +trait Bar +{ + function test() + { + } +} +----- +class Foo extends Bar implements ABC, \DEF, namespace\GHI +{ + var $a = 'foo'; + private $b = 'bar'; + static $c = 'baz'; + function test() + { + $this->a = 'bar'; + echo 'test'; + } + protected function baz() + { + } + public function foo() + { + } + static abstract function bar() + { + } +} +trait Bar +{ + function test() + { + } +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/class_const.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/class_const.test new file mode 100644 index 0000000..e73ad43 --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/class_const.test @@ -0,0 +1,20 @@ +Class constants +----- + $val) { + +} + +foreach ($arr as $key => &$val) { + +} +----- +foreach ($arr as $val) { +} +foreach ($arr as &$val) { +} +foreach ($arr as $key => $val) { +} +foreach ($arr as $key => &$val) { +} \ No newline at end of file diff --git a/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/function_signatures.test b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/function_signatures.test new file mode 100644 index 0000000..af1088a --- /dev/null +++ b/www/multitube/vendor/nikic/php-parser/test/code/prettyPrinter/stmt/function_signatures.test @@ -0,0 +1,43 @@ +Function signatures +----- +parse($code); + $parseTime += microtime(true) - $startTime; + + $startTime = microtime(true); + $code = 'prettyPrint($stmts); + $ppTime += microtime(true) - $startTime; + + try { + $startTime = microtime(true); + $ppStmts = $parser->parse($code); + $reparseTime += microtime(true) - $startTime; + + $startTime = microtime(true); + $same = $nodeDumper->dump($stmts) == $nodeDumper->dump($ppStmts); + $compareTime += microtime(true) - $startTime; + + if (!$same) { + echo $file, ":\n Result of initial parse and parse after pretty print differ\n"; + if ($verbose) { + echo "Pretty printer output:\n=====\n$code\n=====\n\n"; + } + + ++$compareFail; + } + } catch (PhpParser\Error $e) { + echo $file, ":\n Parse of pretty print failed with message: {$e->getMessage()}\n"; + if ($verbose) { + echo "Pretty printer output:\n=====\n$code\n=====\n\n"; + } + + ++$ppFail; + } + } catch (PhpParser\Error $e) { + echo $file, ":\n Parse failed with message: {$e->getMessage()}\n"; + + ++$parseFail; + } +} + +if (0 === $parseFail && 0 === $ppFail && 0 === $compareFail) { + $exit = 0; + echo "\n\n", 'All tests passed.', "\n"; +} else { + $exit = 1; + echo "\n\n", '==========', "\n\n", 'There were: ', "\n"; + if (0 !== $parseFail) { + echo ' ', $parseFail, ' parse failures.', "\n"; + } + if (0 !== $ppFail) { + echo ' ', $ppFail, ' pretty print failures.', "\n"; + } + if (0 !== $compareFail) { + echo ' ', $compareFail, ' compare failures.', "\n"; + } +} + +echo "\n", + 'Tested files: ', $count, "\n", + "\n", + 'Reading files took: ', $readTime, "\n", + 'Parsing took: ', $parseTime, "\n", + 'Pretty printing took: ', $ppTime, "\n", + 'Reparsing took: ', $reparseTime, "\n", + 'Comparing took: ', $compareTime, "\n", + "\n", + 'Total time: ', microtime(true) - $totalStartTime, "\n", + 'Maximum memory usage: ', memory_get_peak_usage(true), "\n"; + +exit($exit); diff --git a/www/multitube/vendor/php-http/client-common/CHANGELOG.md b/www/multitube/vendor/php-http/client-common/CHANGELOG.md new file mode 100644 index 0000000..a8fbc78 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/CHANGELOG.md @@ -0,0 +1,191 @@ +# Change Log + +## 1.10.0 - 2019-11-18 + +### Added + +- Support for Symfony 5 + +## 1.9.1 - 2019-02-02 + +### Added + +- Updated type hints in doc blocks. + +## 1.9.0 - 2019-01-03 + +### Added + +- Support for PSR-18 clients +- Added traits `VersionBridgePlugin` and `VersionBridgeClient` to help plugins and clients to support both + 1.x and 2.x version of `php-http/client-common` and `php-http/httplug`. + +### Changed + +- [RetryPlugin] Renamed the configuration options for the exception retry callback from `decider` to `exception_decider` + and `delay` to `exception_delay`. The old names still work but are deprecated. + +## 1.8.2 - 2018-12-14 + +### Changed + +- When multiple cookies exist, a single header with all cookies is sent as per RFC 6265 Section 5.4 +- AddPathPlugin will now trim of ending slashes in paths + +## 1.8.1 - 2018-10-09 + +### Fixed + +- Reverted change to RetryPlugin so it again waits when retrying to avoid "can only throw objects" error. + +## 1.8.0 - 2018-09-21 + +### Added + + - Add an option on ErrorPlugin to only throw exception on response with 5XX status code. + +### Changed + +- AddPathPlugin no longer add prefix multiple times if a request is restarted - it now only adds the prefix if that request chain has not yet passed through the AddPathPlugin +- RetryPlugin no longer wait for retried requests and use a deferred promise instead + +### Fixed + +- Decoder plugin will now remove header when there is no more encoding, instead of setting to an empty array + + +## 1.7.0 - 2017-11-30 + +### Added + +- Symfony 4 support + +### Changed + +- Strict comparison in DecoderPlugin + +## 1.6.0 - 2017-10-16 + +### Added + +- Add HttpClientPool client to leverage load balancing and fallback mechanism [see the documentation](http://docs.php-http.org/en/latest/components/client-common.html) for more details. +- `PluginClientFactory` to create `PluginClient` instances. +- Added new option 'delay' for `RetryPlugin`. +- Added new option 'decider' for `RetryPlugin`. +- Supports more cookie date formats in the Cookie Plugin + +### Changed + +- The `RetryPlugin` does now wait between retries. To disable/change this feature you must write something like: + +```php +$plugin = new RetryPlugin(['delay' => function(RequestInterface $request, Exception $e, $retries) { + return 0; +}); +``` + +### Deprecated + +- The `debug_plugins` option for `PluginClient` is deprecated and will be removed in 2.0. Use the decorator design pattern instead like in [ProfilePlugin](https://github.com/php-http/HttplugBundle/blob/de33f9c14252f22093a5ec7d84f17535ab31a384/Collector/ProfilePlugin.php). + +## 1.5.0 - 2017-03-30 + +### Added + +- `QueryDefaultsPlugin` to add default query parameters. + +## 1.4.2 - 2017-03-18 + +### Deprecated + +- `DecoderPlugin` does not longer claim to support `compress` content encoding + +### Fixed + +- `CookiePlugin` allows main domain cookies to be sent/stored for subdomains +- `DecoderPlugin` uses the right `FilteredStream` to handle `deflate` content encoding + + +## 1.4.1 - 2017-02-20 + +### Fixed + +- Cast return value of `StreamInterface::getSize` to string in `ContentLengthPlugin` + + +## 1.4.0 - 2016-11-04 + +### Added + +- Add Path plugin +- Base URI plugin that combines Add Host and Add Path plugins + + +## 1.3.0 - 2016-10-16 + +### Changed + +- Fix Emulated Trait to use Http based promise which respect the HttpAsyncClient interface +- Require Httplug 1.1 where we use HTTP specific promises. +- RedirectPlugin: use the full URL instead of the URI to properly keep track of redirects +- Add AddPathPlugin for API URLs with base path +- Add BaseUriPlugin that combines AddHostPlugin and AddPathPlugin + + +## 1.2.1 - 2016-07-26 + +### Changed + +- AddHostPlugin also sets the port if specified + + +## 1.2.0 - 2016-07-14 + +### Added + +- Suggest separate plugins in composer.json +- Introduced `debug_plugins` option for `PluginClient` + + +## 1.1.0 - 2016-05-04 + +### Added + +- Add a flexible http client providing both contract, and only emulating what's necessary +- HTTP Client Router: route requests to underlying clients +- Plugin client and core plugins moved here from `php-http/plugins` + +### Deprecated + +- Extending client classes, they will be made final in version 2.0 + + +## 1.0.0 - 2016-01-27 + +### Changed + +- Remove useless interface in BatchException + + +## 0.2.0 - 2016-01-12 + +### Changed + +- Updated package files +- Updated HTTPlug to RC1 + + +## 0.1.1 - 2015-12-26 + +### Added + +- Emulated clients + + +## 0.1.0 - 2015-12-25 + +### Added + +- Batch client from utils +- Methods client from utils +- Emulators and decorators from client-tools diff --git a/www/multitube/vendor/php-http/client-common/LICENSE b/www/multitube/vendor/php-http/client-common/LICENSE new file mode 100644 index 0000000..4558d6f --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2016 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/client-common/README.md b/www/multitube/vendor/php-http/client-common/README.md new file mode 100644 index 0000000..017bfce --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/README.md @@ -0,0 +1,55 @@ +# HTTP Client Common + +[![Latest Version](https://img.shields.io/github/release/php-http/client-common.svg?style=flat-square)](https://github.com/php-http/client-common/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/travis/php-http/client-common.svg?style=flat-square)](https://travis-ci.org/php-http/client-common) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/client-common.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/client-common) +[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/client-common.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/client-common) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/client-common.svg?style=flat-square)](https://packagist.org/packages/php-http/client-common) + +**Common HTTP Client implementations and tools for HTTPlug.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/client-common +``` + + +## Usage + +This package provides common tools for HTTP Clients: + +- BatchClient to handle sending requests in parallel +- A convenience client with HTTP method names as class methods +- Emulator, decorator layers for sync/async clients + + +## Documentation + +Please see the [official documentation](http://docs.php-http.org/en/latest/components/client-common.html). + + +## Testing + +``` bash +$ composer test +``` + + +## Contributing + +Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html). + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/client-common/composer.json b/www/multitube/vendor/php-http/client-common/composer.json new file mode 100644 index 0000000..cce1f4f --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/composer.json @@ -0,0 +1,43 @@ +{ + "name": "php-http/client-common", + "description": "Common HTTP Client implementations and tools for HTTPlug", + "license": "MIT", + "keywords": ["http", "client", "httplug", "common"], + "homepage": "http://httplug.io", + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": "^5.4 || ^7.0", + "php-http/httplug": "^1.1", + "php-http/message-factory": "^1.0", + "php-http/message": "^1.6", + "symfony/options-resolver": "^2.6 || ^3.0 || ^4.0 || ^5.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.5 || ^3.4 || ^4.2", + "guzzlehttp/psr7": "^1.4" + }, + "suggest": { + "php-http/logger-plugin": "PSR-3 Logger plugin", + "php-http/cache-plugin": "PSR-6 Cache plugin", + "php-http/stopwatch-plugin": "Symfony Stopwatch plugin" + }, + "autoload": { + "psr-4": { + "Http\\Client\\Common\\": "src/" + } + }, + "scripts": { + "test": "vendor/bin/phpspec run", + "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" + }, + "extra": { + "branch-alias": { + "dev-master": "1.10.x-dev" + } + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/BatchClient.php b/www/multitube/vendor/php-http/client-common/src/BatchClient.php new file mode 100644 index 0000000..1aa9950 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/BatchClient.php @@ -0,0 +1,78 @@ + + */ +class BatchClient implements HttpClient +{ + /** + * @var HttpClient|ClientInterface + */ + private $client; + + /** + * @param HttpClient|ClientInterface $client + */ + public function __construct($client) + { + if (!($client instanceof HttpClient) && !($client instanceof ClientInterface)) { + throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface'); + } + + $this->client = $client; + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + return $this->client->sendRequest($request); + } + + /** + * Send several requests. + * + * You may not assume that the requests are executed in a particular order. If the order matters + * for your application, use sendRequest sequentially. + * + * @param RequestInterface[] The requests to send + * + * @return BatchResult Containing one result per request + * + * @throws BatchException If one or more requests fails. The exception gives access to the + * BatchResult with a map of request to result for success, request to + * exception for failures + */ + public function sendRequests(array $requests) + { + $batchResult = new BatchResult(); + + foreach ($requests as $request) { + try { + $response = $this->sendRequest($request); + $batchResult = $batchResult->addResponse($request, $response); + } catch (Exception $e) { + $batchResult = $batchResult->addException($request, $e); + } + } + + if ($batchResult->hasExceptions()) { + throw new BatchException($batchResult); + } + + return $batchResult; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/BatchResult.php b/www/multitube/vendor/php-http/client-common/src/BatchResult.php new file mode 100644 index 0000000..710611d --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/BatchResult.php @@ -0,0 +1,181 @@ + + */ +final class BatchResult +{ + /** + * @var \SplObjectStorage + */ + private $responses; + + /** + * @var \SplObjectStorage + */ + private $exceptions; + + public function __construct() + { + $this->responses = new \SplObjectStorage(); + $this->exceptions = new \SplObjectStorage(); + } + + /** + * Checks if there are any successful responses at all. + * + * @return bool + */ + public function hasResponses() + { + return $this->responses->count() > 0; + } + + /** + * Returns all successful responses. + * + * @return ResponseInterface[] + */ + public function getResponses() + { + $responses = []; + + foreach ($this->responses as $request) { + $responses[] = $this->responses[$request]; + } + + return $responses; + } + + /** + * Checks if there is a successful response for a request. + * + * @param RequestInterface $request + * + * @return bool + */ + public function isSuccessful(RequestInterface $request) + { + return $this->responses->contains($request); + } + + /** + * Returns the response for a successful request. + * + * @param RequestInterface $request + * + * @return ResponseInterface + * + * @throws \UnexpectedValueException If request was not part of the batch or failed + */ + public function getResponseFor(RequestInterface $request) + { + try { + return $this->responses[$request]; + } catch (\UnexpectedValueException $e) { + throw new \UnexpectedValueException('Request not found', $e->getCode(), $e); + } + } + + /** + * Adds a response in an immutable way. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * + * @return BatchResult the new BatchResult with this request-response pair added to it + */ + public function addResponse(RequestInterface $request, ResponseInterface $response) + { + $new = clone $this; + $new->responses->attach($request, $response); + + return $new; + } + + /** + * Checks if there are any unsuccessful requests at all. + * + * @return bool + */ + public function hasExceptions() + { + return $this->exceptions->count() > 0; + } + + /** + * Returns all exceptions for the unsuccessful requests. + * + * @return Exception[] + */ + public function getExceptions() + { + $exceptions = []; + + foreach ($this->exceptions as $request) { + $exceptions[] = $this->exceptions[$request]; + } + + return $exceptions; + } + + /** + * Checks if there is an exception for a request, meaning the request failed. + * + * @param RequestInterface $request + * + * @return bool + */ + public function isFailed(RequestInterface $request) + { + return $this->exceptions->contains($request); + } + + /** + * Returns the exception for a failed request. + * + * @param RequestInterface $request + * + * @return Exception + * + * @throws \UnexpectedValueException If request was not part of the batch or was successful + */ + public function getExceptionFor(RequestInterface $request) + { + try { + return $this->exceptions[$request]; + } catch (\UnexpectedValueException $e) { + throw new \UnexpectedValueException('Request not found', $e->getCode(), $e); + } + } + + /** + * Adds an exception in an immutable way. + * + * @param RequestInterface $request + * @param Exception $exception + * + * @return BatchResult the new BatchResult with this request-exception pair added to it + */ + public function addException(RequestInterface $request, Exception $exception) + { + $new = clone $this; + $new->exceptions->attach($request, $exception); + + return $new; + } + + public function __clone() + { + $this->responses = clone $this->responses; + $this->exceptions = clone $this->exceptions; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Deferred.php b/www/multitube/vendor/php-http/client-common/src/Deferred.php new file mode 100644 index 0000000..075a30e --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Deferred.php @@ -0,0 +1,131 @@ +waitCallback = $waitCallback; + $this->state = Promise::PENDING; + $this->onFulfilledCallbacks = []; + $this->onRejectedCallbacks = []; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + $deferred = new self($this->waitCallback); + + $this->onFulfilledCallbacks[] = function (ResponseInterface $response) use ($onFulfilled, $deferred) { + try { + if (null !== $onFulfilled) { + $response = $onFulfilled($response); + } + $deferred->resolve($response); + } catch (Exception $exception) { + $deferred->reject($exception); + } + }; + + $this->onRejectedCallbacks[] = function (Exception $exception) use ($onRejected, $deferred) { + try { + if (null !== $onRejected) { + $response = $onRejected($exception); + $deferred->resolve($response); + + return; + } + $deferred->reject($exception); + } catch (Exception $newException) { + $deferred->reject($newException); + } + }; + + return $deferred; + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return $this->state; + } + + /** + * Resolve this deferred with a Response. + */ + public function resolve(ResponseInterface $response) + { + if (self::PENDING !== $this->state) { + return; + } + + $this->value = $response; + $this->state = self::FULFILLED; + + foreach ($this->onFulfilledCallbacks as $onFulfilledCallback) { + $onFulfilledCallback($response); + } + } + + /** + * Reject this deferred with an Exception. + */ + public function reject(Exception $exception) + { + if (self::PENDING !== $this->state) { + return; + } + + $this->failure = $exception; + $this->state = self::REJECTED; + + foreach ($this->onRejectedCallbacks as $onRejectedCallback) { + $onRejectedCallback($exception); + } + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if (self::PENDING === $this->state) { + $callback = $this->waitCallback; + $callback(); + } + + if (!$unwrap) { + return; + } + + if (self::FULFILLED === $this->state) { + return $this->value; + } + + throw $this->failure; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php b/www/multitube/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php new file mode 100644 index 0000000..39f89cc --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/EmulatedHttpAsyncClient.php @@ -0,0 +1,32 @@ + + */ +class EmulatedHttpAsyncClient implements HttpClient, HttpAsyncClient +{ + use HttpAsyncClientEmulator; + use HttpClientDecorator; + + /** + * @param HttpClient|ClientInterface $httpClient + */ + public function __construct($httpClient) + { + if (!($httpClient instanceof HttpClient) && !($httpClient instanceof ClientInterface)) { + throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface'); + } + + $this->httpClient = $httpClient; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/EmulatedHttpClient.php b/www/multitube/vendor/php-http/client-common/src/EmulatedHttpClient.php new file mode 100644 index 0000000..01046c8 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/EmulatedHttpClient.php @@ -0,0 +1,27 @@ + + */ +class EmulatedHttpClient implements HttpClient, HttpAsyncClient +{ + use HttpAsyncClientDecorator; + use HttpClientEmulator; + + /** + * @param HttpAsyncClient $httpAsyncClient + */ + public function __construct(HttpAsyncClient $httpAsyncClient) + { + $this->httpAsyncClient = $httpAsyncClient; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/BatchException.php b/www/multitube/vendor/php-http/client-common/src/Exception/BatchException.php new file mode 100644 index 0000000..66a9271 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/BatchException.php @@ -0,0 +1,39 @@ + + */ +final class BatchException extends TransferException +{ + /** + * @var BatchResult + */ + private $result; + + /** + * @param BatchResult $result + */ + public function __construct(BatchResult $result) + { + $this->result = $result; + } + + /** + * Returns the BatchResult that contains all responses and exceptions. + * + * @return BatchResult + */ + public function getResult() + { + return $this->result; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php b/www/multitube/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php new file mode 100644 index 0000000..73ec521 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/CircularRedirectionException.php @@ -0,0 +1,14 @@ + + */ +class CircularRedirectionException extends HttpException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/ClientErrorException.php b/www/multitube/vendor/php-http/client-common/src/Exception/ClientErrorException.php new file mode 100644 index 0000000..b1f6cc8 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/ClientErrorException.php @@ -0,0 +1,14 @@ + + */ +class ClientErrorException extends HttpException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php b/www/multitube/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php new file mode 100644 index 0000000..5d33f98 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/HttpClientNotFoundException.php @@ -0,0 +1,14 @@ + + */ +class HttpClientNotFoundException extends TransferException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/LoopException.php b/www/multitube/vendor/php-http/client-common/src/Exception/LoopException.php new file mode 100644 index 0000000..e834124 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/LoopException.php @@ -0,0 +1,14 @@ + + */ +class LoopException extends RequestException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php b/www/multitube/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php new file mode 100644 index 0000000..ae514cd --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/MultipleRedirectionException.php @@ -0,0 +1,14 @@ + + */ +class MultipleRedirectionException extends HttpException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/Exception/ServerErrorException.php b/www/multitube/vendor/php-http/client-common/src/Exception/ServerErrorException.php new file mode 100644 index 0000000..665d724 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Exception/ServerErrorException.php @@ -0,0 +1,14 @@ + + */ +class ServerErrorException extends HttpException +{ +} diff --git a/www/multitube/vendor/php-http/client-common/src/FlexibleHttpClient.php b/www/multitube/vendor/php-http/client-common/src/FlexibleHttpClient.php new file mode 100644 index 0000000..d0a6e88 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/FlexibleHttpClient.php @@ -0,0 +1,40 @@ + + */ +final class FlexibleHttpClient implements HttpClient, HttpAsyncClient +{ + use HttpClientDecorator; + use HttpAsyncClientDecorator; + + /** + * @param HttpClient|HttpAsyncClient|ClientInterface $client + */ + public function __construct($client) + { + if (!($client instanceof HttpClient) && !($client instanceof HttpAsyncClient) && !($client instanceof ClientInterface)) { + throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient'); + } + + $this->httpClient = $client; + $this->httpAsyncClient = $client; + + if (!($this->httpClient instanceof HttpClient) && !($client instanceof ClientInterface)) { + $this->httpClient = new EmulatedHttpClient($this->httpClient); + } + + if (!($this->httpAsyncClient instanceof HttpAsyncClient)) { + $this->httpAsyncClient = new EmulatedHttpAsyncClient($this->httpAsyncClient); + } + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php b/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php new file mode 100644 index 0000000..6eb576c --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientDecorator.php @@ -0,0 +1,29 @@ + + */ +trait HttpAsyncClientDecorator +{ + /** + * @var HttpAsyncClient + */ + protected $httpAsyncClient; + + /** + * {@inheritdoc} + * + * @see HttpAsyncClient::sendAsyncRequest + */ + public function sendAsyncRequest(RequestInterface $request) + { + return $this->httpAsyncClient->sendAsyncRequest($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php b/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php new file mode 100644 index 0000000..c0ba354 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpAsyncClientEmulator.php @@ -0,0 +1,36 @@ + + */ +trait HttpAsyncClientEmulator +{ + /** + * {@inheritdoc} + * + * @see HttpClient::sendRequest + */ + abstract public function sendRequest(RequestInterface $request); + + /** + * {@inheritdoc} + * + * @see HttpAsyncClient::sendAsyncRequest + */ + public function sendAsyncRequest(RequestInterface $request) + { + try { + return new Promise\HttpFulfilledPromise($this->sendRequest($request)); + } catch (Exception $e) { + return new Promise\HttpRejectedPromise($e); + } + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientDecorator.php b/www/multitube/vendor/php-http/client-common/src/HttpClientDecorator.php new file mode 100644 index 0000000..0b7e48e --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientDecorator.php @@ -0,0 +1,30 @@ + + */ +trait HttpClientDecorator +{ + /** + * @var HttpClient|ClientInterface + */ + protected $httpClient; + + /** + * {@inheritdoc} + * + * @see HttpClient::sendRequest + */ + public function sendRequest(RequestInterface $request) + { + return $this->httpClient->sendRequest($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientEmulator.php b/www/multitube/vendor/php-http/client-common/src/HttpClientEmulator.php new file mode 100644 index 0000000..dbec1ab --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientEmulator.php @@ -0,0 +1,32 @@ + + */ +trait HttpClientEmulator +{ + /** + * {@inheritdoc} + * + * @see HttpClient::sendRequest + */ + public function sendRequest(RequestInterface $request) + { + $promise = $this->sendAsyncRequest($request); + + return $promise->wait(); + } + + /** + * {@inheritdoc} + * + * @see HttpAsyncClient::sendAsyncRequest + */ + abstract public function sendAsyncRequest(RequestInterface $request); +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientPool.php b/www/multitube/vendor/php-http/client-common/src/HttpClientPool.php new file mode 100644 index 0000000..c51d044 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientPool.php @@ -0,0 +1,60 @@ +clientPool[] = $client; + } + + /** + * Return an http client given a specific strategy. + * + * @throws HttpClientNotFoundException When no http client has been found into the pool + * + * @return HttpClientPoolItem Return a http client that can do both sync or async + */ + abstract protected function chooseHttpClient(); + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + return $this->chooseHttpClient()->sendAsyncRequest($request); + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + return $this->chooseHttpClient()->sendRequest($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php new file mode 100644 index 0000000..6299cce --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/LeastUsedClientPool.php @@ -0,0 +1,45 @@ + + */ +final class LeastUsedClientPool extends HttpClientPool +{ + /** + * {@inheritdoc} + */ + protected function chooseHttpClient() + { + $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) { + return !$clientPoolItem->isDisabled(); + }); + + if (0 === count($clientPool)) { + throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool'); + } + + usort($clientPool, function (HttpClientPoolItem $clientA, HttpClientPoolItem $clientB) { + if ($clientA->getSendingRequestCount() === $clientB->getSendingRequestCount()) { + return 0; + } + + if ($clientA->getSendingRequestCount() < $clientB->getSendingRequestCount()) { + return -1; + } + + return 1; + }); + + return reset($clientPool); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php new file mode 100644 index 0000000..3255f86 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RandomClientPool.php @@ -0,0 +1,31 @@ + + */ +final class RandomClientPool extends HttpClientPool +{ + /** + * {@inheritdoc} + */ + protected function chooseHttpClient() + { + $clientPool = array_filter($this->clientPool, function (HttpClientPoolItem $clientPoolItem) { + return !$clientPoolItem->isDisabled(); + }); + + if (0 === count($clientPool)) { + throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool'); + } + + return $clientPool[array_rand($clientPool)]; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php new file mode 100644 index 0000000..8d8e40a --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientPool/RoundRobinClientPool.php @@ -0,0 +1,41 @@ + + */ +final class RoundRobinClientPool extends HttpClientPool +{ + /** + * {@inheritdoc} + */ + protected function chooseHttpClient() + { + $last = current($this->clientPool); + + do { + $client = next($this->clientPool); + + if (false === $client) { + $client = reset($this->clientPool); + + if (false === $client) { + throw new HttpClientNotFoundException('Cannot choose a http client as there is no one present in the pool'); + } + } + + // Case when there is only one and the last one has been disabled + if ($last === $client && $client->isDisabled()) { + throw new HttpClientNotFoundException('Cannot choose a http client as there is no one enabled in the pool'); + } + } while ($client->isDisabled()); + + return $client; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientPoolItem.php b/www/multitube/vendor/php-http/client-common/src/HttpClientPoolItem.php new file mode 100644 index 0000000..5c79137 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientPoolItem.php @@ -0,0 +1,179 @@ + + */ +class HttpClientPoolItem implements HttpClient, HttpAsyncClient +{ + /** + * @var int Number of request this client is currently sending + */ + private $sendingRequestCount = 0; + + /** + * @var \DateTime|null Time when this client has been disabled or null if enable + */ + private $disabledAt; + + /** + * @var int|null Number of seconds after this client is reenable, by default null: never reenable this client + */ + private $reenableAfter; + + /** + * @var FlexibleHttpClient A http client responding to async and sync request + */ + private $client; + + /** + * @param HttpClient|HttpAsyncClient|ClientInterface $client + * @param null|int $reenableAfter Number of seconds after this client is reenable + */ + public function __construct($client, $reenableAfter = null) + { + $this->client = new FlexibleHttpClient($client); + $this->reenableAfter = $reenableAfter; + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + if ($this->isDisabled()) { + throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request); + } + + try { + $this->incrementRequestCount(); + $response = $this->client->sendRequest($request); + $this->decrementRequestCount(); + } catch (Exception $e) { + $this->disable(); + $this->decrementRequestCount(); + + throw $e; + } + + return $response; + } + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + if ($this->isDisabled()) { + throw new Exception\RequestException('Cannot send the request as this client has been disabled', $request); + } + + $this->incrementRequestCount(); + + return $this->client->sendAsyncRequest($request)->then(function ($response) { + $this->decrementRequestCount(); + + return $response; + }, function ($exception) { + $this->disable(); + $this->decrementRequestCount(); + + throw $exception; + }); + } + + /** + * Whether this client is disabled or not. + * + * Will also reactivate this client if possible + * + * @internal + * + * @return bool + */ + public function isDisabled() + { + $disabledAt = $this->getDisabledAt(); + + if (null !== $this->reenableAfter && null !== $disabledAt) { + // Reenable after a certain time + $now = new \DateTime(); + + if (($now->getTimestamp() - $disabledAt->getTimestamp()) >= $this->reenableAfter) { + $this->enable(); + + return false; + } + + return true; + } + + return null !== $disabledAt; + } + + /** + * Get current number of request that is send by the underlying http client. + * + * @internal + * + * @return int + */ + public function getSendingRequestCount() + { + return $this->sendingRequestCount; + } + + /** + * Return when this client has been disabled or null if it's enabled. + * + * @return \DateTime|null + */ + private function getDisabledAt() + { + return $this->disabledAt; + } + + /** + * Increment the request count. + */ + private function incrementRequestCount() + { + ++$this->sendingRequestCount; + } + + /** + * Decrement the request count. + */ + private function decrementRequestCount() + { + --$this->sendingRequestCount; + } + + /** + * Enable the current client. + */ + private function enable() + { + $this->disabledAt = null; + } + + /** + * Disable the current client. + */ + private function disable() + { + $this->disabledAt = new \DateTime('now'); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpClientRouter.php b/www/multitube/vendor/php-http/client-common/src/HttpClientRouter.php new file mode 100644 index 0000000..8f897d2 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpClientRouter.php @@ -0,0 +1,75 @@ + + */ +final class HttpClientRouter implements HttpClient, HttpAsyncClient +{ + /** + * @var array + */ + private $clients = []; + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + $client = $this->chooseHttpClient($request); + + return $client->sendRequest($request); + } + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + $client = $this->chooseHttpClient($request); + + return $client->sendAsyncRequest($request); + } + + /** + * Add a client to the router. + * + * @param HttpClient|HttpAsyncClient|ClientInterface $client + * @param RequestMatcher $requestMatcher + */ + public function addClient($client, RequestMatcher $requestMatcher) + { + $this->clients[] = [ + 'matcher' => $requestMatcher, + 'client' => new FlexibleHttpClient($client), + ]; + } + + /** + * Choose an HTTP client given a specific request. + * + * @param RequestInterface $request + * + * @return HttpClient|HttpAsyncClient|ClientInterface + */ + protected function chooseHttpClient(RequestInterface $request) + { + foreach ($this->clients as $client) { + if ($client['matcher']->matches($request)) { + return $client['client']; + } + } + + throw new RequestException('No client found for the specified request', $request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/HttpMethodsClient.php b/www/multitube/vendor/php-http/client-common/src/HttpMethodsClient.php new file mode 100644 index 0000000..c462c10 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/HttpMethodsClient.php @@ -0,0 +1,210 @@ +get('/foo') + * ->post('/bar') + * ; + * + * The client also exposes the sendRequest methods of the wrapped HttpClient. + * + * @author Márk Sági-Kazár + * @author David Buchmann + */ +class HttpMethodsClient implements HttpClient +{ + /** + * @var HttpClient|ClientInterface + */ + private $httpClient; + + /** + * @var RequestFactory + */ + private $requestFactory; + + /** + * @param HttpClient|ClientInterface $httpClient The client to send requests with + * @param RequestFactory $requestFactory The message factory to create requests + */ + public function __construct($httpClient, RequestFactory $requestFactory) + { + if (!($httpClient instanceof HttpClient) && !($httpClient instanceof ClientInterface)) { + throw new \LogicException('Client must be an instance of Http\\Client\\HttpClient or Psr\\Http\\Client\\ClientInterface'); + } + + $this->httpClient = $httpClient; + $this->requestFactory = $requestFactory; + } + + /** + * Sends a GET request. + * + * @param string|UriInterface $uri + * @param array $headers + * + * @throws Exception + * + * @return ResponseInterface + */ + public function get($uri, array $headers = []) + { + return $this->send('GET', $uri, $headers, null); + } + + /** + * Sends an HEAD request. + * + * @param string|UriInterface $uri + * @param array $headers + * + * @throws Exception + * + * @return ResponseInterface + */ + public function head($uri, array $headers = []) + { + return $this->send('HEAD', $uri, $headers, null); + } + + /** + * Sends a TRACE request. + * + * @param string|UriInterface $uri + * @param array $headers + * + * @throws Exception + * + * @return ResponseInterface + */ + public function trace($uri, array $headers = []) + { + return $this->send('TRACE', $uri, $headers, null); + } + + /** + * Sends a POST request. + * + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function post($uri, array $headers = [], $body = null) + { + return $this->send('POST', $uri, $headers, $body); + } + + /** + * Sends a PUT request. + * + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function put($uri, array $headers = [], $body = null) + { + return $this->send('PUT', $uri, $headers, $body); + } + + /** + * Sends a PATCH request. + * + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function patch($uri, array $headers = [], $body = null) + { + return $this->send('PATCH', $uri, $headers, $body); + } + + /** + * Sends a DELETE request. + * + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function delete($uri, array $headers = [], $body = null) + { + return $this->send('DELETE', $uri, $headers, $body); + } + + /** + * Sends an OPTIONS request. + * + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function options($uri, array $headers = [], $body = null) + { + return $this->send('OPTIONS', $uri, $headers, $body); + } + + /** + * Sends a request with any HTTP method. + * + * @param string $method HTTP method to use + * @param string|UriInterface $uri + * @param array $headers + * @param string|StreamInterface|null $body + * + * @throws Exception + * + * @return ResponseInterface + */ + public function send($method, $uri, array $headers = [], $body = null) + { + return $this->sendRequest($this->requestFactory->createRequest( + $method, + $uri, + $headers, + $body + )); + } + + /** + * Forward to the underlying HttpClient. + * + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + return $this->httpClient->sendRequest($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin.php new file mode 100644 index 0000000..89a2a62 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin.php @@ -0,0 +1,32 @@ + + */ +interface Plugin +{ + /** + * Handle the request and return the response coming from the next callable. + * + * @see http://docs.php-http.org/en/latest/plugins/build-your-own.html + * + * @param RequestInterface $request + * @param callable $next Next middleware in the chain, the request is passed as the first argument + * @param callable $first First middleware in the chain, used to to restart a request + * + * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception (The same as HttpAsyncClient). + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first); +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php new file mode 100644 index 0000000..29ab8ae --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/AddHostPlugin.php @@ -0,0 +1,77 @@ + + */ +final class AddHostPlugin implements Plugin +{ + /** + * @var UriInterface + */ + private $host; + + /** + * @var bool + */ + private $replace; + + /** + * @param UriInterface $host + * @param array $config { + * + * @var bool $replace True will replace all hosts, false will only add host when none is specified. + * } + */ + public function __construct(UriInterface $host, array $config = []) + { + if ('' === $host->getHost()) { + throw new \LogicException('Host can not be empty'); + } + + $this->host = $host; + + $resolver = new OptionsResolver(); + $this->configureOptions($resolver); + $options = $resolver->resolve($config); + + $this->replace = $options['replace']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + if ($this->replace || '' === $request->getUri()->getHost()) { + $uri = $request->getUri() + ->withHost($this->host->getHost()) + ->withScheme($this->host->getScheme()) + ->withPort($this->host->getPort()) + ; + + $request = $request->withUri($uri); + } + + return $next($request); + } + + /** + * @param OptionsResolver $resolver + */ + private function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'replace' => false, + ]); + $resolver->setAllowedTypes('replace', 'bool'); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php new file mode 100644 index 0000000..0a1bca2 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/AddPathPlugin.php @@ -0,0 +1,60 @@ + + */ +final class AddPathPlugin implements Plugin +{ + /** + * @var UriInterface + */ + private $uri; + + /** + * Stores identifiers of the already altered requests. + * + * @var array + */ + private $alteredRequests = []; + + /** + * @param UriInterface $uri + */ + public function __construct(UriInterface $uri) + { + if ('' === $uri->getPath()) { + throw new \LogicException('URI path cannot be empty'); + } + + if ('/' === substr($uri->getPath(), -1)) { + $uri = $uri->withPath(rtrim($uri->getPath(), '/')); + } + + $this->uri = $uri; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $identifier = spl_object_hash((object) $first); + + if (!array_key_exists($identifier, $this->alteredRequests)) { + $request = $request->withUri($request->getUri() + ->withPath($this->uri->getPath().$request->getUri()->getPath()) + ); + $this->alteredRequests[$identifier] = $identifier; + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php new file mode 100644 index 0000000..194712f --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/AuthenticationPlugin.php @@ -0,0 +1,38 @@ + + */ +final class AuthenticationPlugin implements Plugin +{ + /** + * @var Authentication An authentication system + */ + private $authentication; + + /** + * @param Authentication $authentication + */ + public function __construct(Authentication $authentication) + { + $this->authentication = $authentication; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $request = $this->authentication->authenticate($request); + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php new file mode 100644 index 0000000..2c2a775 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/BaseUriPlugin.php @@ -0,0 +1,54 @@ + + */ +final class BaseUriPlugin implements Plugin +{ + /** + * @var AddHostPlugin + */ + private $addHostPlugin; + + /** + * @var AddPathPlugin|null + */ + private $addPathPlugin = null; + + /** + * @param UriInterface $uri Has to contain a host name and cans have a path. + * @param array $hostConfig Config for AddHostPlugin. @see AddHostPlugin::configureOptions + */ + public function __construct(UriInterface $uri, array $hostConfig = []) + { + $this->addHostPlugin = new AddHostPlugin($uri, $hostConfig); + + if (rtrim($uri->getPath(), '/')) { + $this->addPathPlugin = new AddPathPlugin($uri); + } + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $addHostNext = function (RequestInterface $request) use ($next, $first) { + return $this->addHostPlugin->handleRequest($request, $next, $first); + }; + + if ($this->addPathPlugin) { + return $this->addPathPlugin->handleRequest($request, $addHostNext, $first); + } + + return $addHostNext($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php new file mode 100644 index 0000000..0f7aafa --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/ContentLengthPlugin.php @@ -0,0 +1,36 @@ + + */ +final class ContentLengthPlugin implements Plugin +{ + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + if (!$request->hasHeader('Content-Length')) { + $stream = $request->getBody(); + + // Cannot determine the size so we use a chunk stream + if (null === $stream->getSize()) { + $stream = new ChunkStream($stream); + $request = $request->withBody($stream); + $request = $request->withAddedHeader('Transfer-Encoding', 'chunked'); + } else { + $request = $request->withHeader('Content-Length', (string) $stream->getSize()); + } + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php new file mode 100644 index 0000000..8ef1d62 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/ContentTypePlugin.php @@ -0,0 +1,123 @@ + + */ +final class ContentTypePlugin implements Plugin +{ + /** + * Allow to disable the content type detection when stream is too large (as it can consume a lot of resource). + * + * @var bool + * + * true skip the content type detection + * false detect the content type (default value) + */ + protected $skipDetection; + + /** + * Determine the size stream limit for which the detection as to be skipped (default to 16Mb). + * + * @var int + */ + protected $sizeLimit; + + /** + * @param array $config { + * + * @var bool $skip_detection True skip detection if stream size is bigger than $size_limit. + * @var int $size_limit size stream limit for which the detection as to be skipped. + * } + */ + public function __construct(array $config = []) + { + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'skip_detection' => false, + 'size_limit' => 16000000, + ]); + $resolver->setAllowedTypes('skip_detection', 'bool'); + $resolver->setAllowedTypes('size_limit', 'int'); + + $options = $resolver->resolve($config); + + $this->skipDetection = $options['skip_detection']; + $this->sizeLimit = $options['size_limit']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + if (!$request->hasHeader('Content-Type')) { + $stream = $request->getBody(); + $streamSize = $stream->getSize(); + + if (!$stream->isSeekable()) { + return $next($request); + } + + if (0 === $streamSize) { + return $next($request); + } + + if ($this->skipDetection && (null === $streamSize || $streamSize >= $this->sizeLimit)) { + return $next($request); + } + + if ($this->isJson($stream)) { + $request = $request->withHeader('Content-Type', 'application/json'); + + return $next($request); + } + + if ($this->isXml($stream)) { + $request = $request->withHeader('Content-Type', 'application/xml'); + + return $next($request); + } + } + + return $next($request); + } + + /** + * @param $stream StreamInterface + * + * @return bool + */ + private function isJson($stream) + { + $stream->rewind(); + + json_decode($stream->getContents()); + + return JSON_ERROR_NONE === json_last_error(); + } + + /** + * @param $stream StreamInterface + * + * @return \SimpleXMLElement|false + */ + private function isXml($stream) + { + $stream->rewind(); + + $previousValue = libxml_use_internal_errors(true); + $isXml = simplexml_load_string($stream->getContents()); + libxml_use_internal_errors($previousValue); + + return $isXml; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/CookiePlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/CookiePlugin.php new file mode 100644 index 0000000..156532a --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/CookiePlugin.php @@ -0,0 +1,185 @@ + + */ +final class CookiePlugin implements Plugin +{ + /** + * Cookie storage. + * + * @var CookieJar + */ + private $cookieJar; + + /** + * @param CookieJar $cookieJar + */ + public function __construct(CookieJar $cookieJar) + { + $this->cookieJar = $cookieJar; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $cookies = []; + foreach ($this->cookieJar->getCookies() as $cookie) { + if ($cookie->isExpired()) { + continue; + } + + if (!$cookie->matchDomain($request->getUri()->getHost())) { + continue; + } + + if (!$cookie->matchPath($request->getUri()->getPath())) { + continue; + } + + if ($cookie->isSecure() && ('https' !== $request->getUri()->getScheme())) { + continue; + } + + $cookies[] = sprintf('%s=%s', $cookie->getName(), $cookie->getValue()); + } + + if (!empty($cookies)) { + $request = $request->withAddedHeader('Cookie', implode('; ', array_unique($cookies))); + } + + return $next($request)->then(function (ResponseInterface $response) use ($request) { + if ($response->hasHeader('Set-Cookie')) { + $setCookies = $response->getHeader('Set-Cookie'); + + foreach ($setCookies as $setCookie) { + $cookie = $this->createCookie($request, $setCookie); + + // Cookie invalid do not use it + if (null === $cookie) { + continue; + } + + // Restrict setting cookie from another domain + if (!preg_match("/\.{$cookie->getDomain()}$/", '.'.$request->getUri()->getHost())) { + continue; + } + + $this->cookieJar->addCookie($cookie); + } + } + + return $response; + }); + } + + /** + * Creates a cookie from a string. + * + * @param RequestInterface $request + * @param $setCookie + * + * @return Cookie|null + * + * @throws TransferException + */ + private function createCookie(RequestInterface $request, $setCookie) + { + $parts = array_map('trim', explode(';', $setCookie)); + + if (empty($parts) || !strpos($parts[0], '=')) { + return; + } + + list($name, $cookieValue) = $this->createValueKey(array_shift($parts)); + + $maxAge = null; + $expires = null; + $domain = $request->getUri()->getHost(); + $path = $request->getUri()->getPath(); + $secure = false; + $httpOnly = false; + + // Add the cookie pieces into the parsed data array + foreach ($parts as $part) { + list($key, $value) = $this->createValueKey($part); + + switch (strtolower($key)) { + case 'expires': + try { + $expires = CookieUtil::parseDate($value); + } catch (UnexpectedValueException $e) { + throw new TransferException( + sprintf( + 'Cookie header `%s` expires value `%s` could not be converted to date', + $name, + $value + ), + 0, + $e + ); + } + + break; + + case 'max-age': + $maxAge = (int) $value; + + break; + + case 'domain': + $domain = $value; + + break; + + case 'path': + $path = $value; + + break; + + case 'secure': + $secure = true; + + break; + + case 'httponly': + $httpOnly = true; + + break; + } + } + + return new Cookie($name, $cookieValue, $maxAge, $domain, $path, $secure, $httpOnly, $expires); + } + + /** + * Separates key/value pair from cookie. + * + * @param $part + * + * @return array + */ + private function createValueKey($part) + { + $parts = explode('=', $part, 2); + $key = trim($parts[0]); + $value = isset($parts[1]) ? trim($parts[1]) : true; + + return [$key, $value]; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php new file mode 100644 index 0000000..0239d40 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/DecoderPlugin.php @@ -0,0 +1,144 @@ + + */ +final class DecoderPlugin implements Plugin +{ + /** + * @var bool Whether this plugin decode stream with value in the Content-Encoding header (default to true). + * + * If set to false only the Transfer-Encoding header will be used + */ + private $useContentEncoding; + + /** + * @param array $config { + * + * @var bool $use_content_encoding Whether this plugin should look at the Content-Encoding header first or only at the Transfer-Encoding (defaults to true). + * } + */ + public function __construct(array $config = []) + { + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'use_content_encoding' => true, + ]); + $resolver->setAllowedTypes('use_content_encoding', 'bool'); + $options = $resolver->resolve($config); + + $this->useContentEncoding = $options['use_content_encoding']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $encodings = extension_loaded('zlib') ? ['gzip', 'deflate'] : ['identity']; + + if ($this->useContentEncoding) { + $request = $request->withHeader('Accept-Encoding', $encodings); + } + $encodings[] = 'chunked'; + $request = $request->withHeader('TE', $encodings); + + return $next($request)->then(function (ResponseInterface $response) { + return $this->decodeResponse($response); + }); + } + + /** + * Decode a response body given its Transfer-Encoding or Content-Encoding value. + * + * @param ResponseInterface $response Response to decode + * + * @return ResponseInterface New response decoded + */ + private function decodeResponse(ResponseInterface $response) + { + $response = $this->decodeOnEncodingHeader('Transfer-Encoding', $response); + + if ($this->useContentEncoding) { + $response = $this->decodeOnEncodingHeader('Content-Encoding', $response); + } + + return $response; + } + + /** + * Decode a response on a specific header (content encoding or transfer encoding mainly). + * + * @param string $headerName Name of the header + * @param ResponseInterface $response Response + * + * @return ResponseInterface A new instance of the response decoded + */ + private function decodeOnEncodingHeader($headerName, ResponseInterface $response) + { + if ($response->hasHeader($headerName)) { + $encodings = $response->getHeader($headerName); + $newEncodings = []; + + while ($encoding = array_pop($encodings)) { + $stream = $this->decorateStream($encoding, $response->getBody()); + + if (false === $stream) { + array_unshift($newEncodings, $encoding); + + continue; + } + + $response = $response->withBody($stream); + } + + if (\count($newEncodings) > 0) { + $response = $response->withHeader($headerName, $newEncodings); + } else { + $response = $response->withoutHeader($headerName); + } + } + + return $response; + } + + /** + * Decorate a stream given an encoding. + * + * @param string $encoding + * @param StreamInterface $stream + * + * @return StreamInterface|false A new stream interface or false if encoding is not supported + */ + private function decorateStream($encoding, StreamInterface $stream) + { + if ('chunked' === strtolower($encoding)) { + return new Encoding\DechunkStream($stream); + } + + if ('deflate' === strtolower($encoding)) { + return new Encoding\DecompressStream($stream); + } + + if ('gzip' === strtolower($encoding)) { + return new Encoding\GzipDecodeStream($stream); + } + + return false; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php new file mode 100644 index 0000000..bcc1c67 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/ErrorPlugin.php @@ -0,0 +1,81 @@ + + */ +final class ErrorPlugin implements Plugin +{ + /** + * @var bool Whether this plugin should only throw 5XX Exceptions (default to false). + * + * If set to true 4XX Responses code will never throw an exception + */ + private $onlyServerException; + + /** + * @param array $config { + * + * @var bool only_server_exception Whether this plugin should only throw 5XX Exceptions (default to false). + * } + */ + public function __construct(array $config = []) + { + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'only_server_exception' => false, + ]); + $resolver->setAllowedTypes('only_server_exception', 'bool'); + $options = $resolver->resolve($config); + + $this->onlyServerException = $options['only_server_exception']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $promise = $next($request); + + return $promise->then(function (ResponseInterface $response) use ($request) { + return $this->transformResponseToException($request, $response); + }); + } + + /** + * Transform response to an error if possible. + * + * @param RequestInterface $request Request of the call + * @param ResponseInterface $response Response of the call + * + * @throws ClientErrorException If response status code is a 4xx + * @throws ServerErrorException If response status code is a 5xx + * + * @return ResponseInterface If status code is not in 4xx or 5xx return response + */ + protected function transformResponseToException(RequestInterface $request, ResponseInterface $response) + { + if (!$this->onlyServerException && $response->getStatusCode() >= 400 && $response->getStatusCode() < 500) { + throw new ClientErrorException($response->getReasonPhrase(), $request, $response); + } + + if ($response->getStatusCode() >= 500 && $response->getStatusCode() < 600) { + throw new ServerErrorException($response->getReasonPhrase(), $request, $response); + } + + return $response; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php new file mode 100644 index 0000000..26fd813 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderAppendPlugin.php @@ -0,0 +1,45 @@ + + */ +final class HeaderAppendPlugin implements Plugin +{ + /** + * @var array + */ + private $headers = []; + + /** + * @param array $headers Hashmap of header name to header value + */ + public function __construct(array $headers) + { + $this->headers = $headers; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + foreach ($this->headers as $header => $headerValue) { + $request = $request->withAddedHeader($header, $headerValue); + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php new file mode 100644 index 0000000..6dfc111 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderDefaultsPlugin.php @@ -0,0 +1,43 @@ + + */ +final class HeaderDefaultsPlugin implements Plugin +{ + /** + * @var array + */ + private $headers = []; + + /** + * @param array $headers Hashmap of header name to header value + */ + public function __construct(array $headers) + { + $this->headers = $headers; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + foreach ($this->headers as $header => $headerValue) { + if (!$request->hasHeader($header)) { + $request = $request->withHeader($header, $headerValue); + } + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php new file mode 100644 index 0000000..fc9c19d --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderRemovePlugin.php @@ -0,0 +1,41 @@ + + */ +final class HeaderRemovePlugin implements Plugin +{ + /** + * @var array + */ + private $headers = []; + + /** + * @param array $headers List of header names to remove from the request + */ + public function __construct(array $headers) + { + $this->headers = $headers; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + foreach ($this->headers as $header) { + if ($request->hasHeader($header)) { + $request = $request->withoutHeader($header); + } + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php new file mode 100644 index 0000000..75f11d4 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/HeaderSetPlugin.php @@ -0,0 +1,41 @@ + + */ +final class HeaderSetPlugin implements Plugin +{ + /** + * @var array + */ + private $headers = []; + + /** + * @param array $headers Hashmap of header name to header value + */ + public function __construct(array $headers) + { + $this->headers = $headers; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + foreach ($this->headers as $header => $headerValue) { + $request = $request->withHeader($header, $headerValue); + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php new file mode 100644 index 0000000..5abddbd --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/HistoryPlugin.php @@ -0,0 +1,49 @@ + + */ +final class HistoryPlugin implements Plugin +{ + /** + * Journal use to store request / responses / exception. + * + * @var Journal + */ + private $journal; + + /** + * @param Journal $journal + */ + public function __construct(Journal $journal) + { + $this->journal = $journal; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $journal = $this->journal; + + return $next($request)->then(function (ResponseInterface $response) use ($request, $journal) { + $journal->addSuccess($request, $response); + + return $response; + }, function (Exception $exception) use ($request, $journal) { + $journal->addFailure($request, $exception); + + throw $exception; + }); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/Journal.php b/www/multitube/vendor/php-http/client-common/src/Plugin/Journal.php new file mode 100644 index 0000000..15f3095 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/Journal.php @@ -0,0 +1,31 @@ + + */ +interface Journal +{ + /** + * Record a successful call. + * + * @param RequestInterface $request Request use to make the call + * @param ResponseInterface $response Response returned by the call + */ + public function addSuccess(RequestInterface $request, ResponseInterface $response); + + /** + * Record a failed call. + * + * @param RequestInterface $request Request use to make the call + * @param Exception $exception Exception returned by the call + */ + public function addFailure(RequestInterface $request, Exception $exception); +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php new file mode 100644 index 0000000..d9c06d6 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/QueryDefaultsPlugin.php @@ -0,0 +1,47 @@ + + */ +final class QueryDefaultsPlugin implements Plugin +{ + /** + * @var array + */ + private $queryParams = []; + + /** + * @param array $queryParams Hashmap of query name to query value. Names and values must not be url encoded as + * this plugin will encode them + */ + public function __construct(array $queryParams) + { + $this->queryParams = $queryParams; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $uri = $request->getUri(); + + parse_str($uri->getQuery(), $query); + $query += $this->queryParams; + + $request = $request->withUri( + $uri->withQuery(http_build_query($query)) + ); + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php new file mode 100644 index 0000000..d2f442e --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/RedirectPlugin.php @@ -0,0 +1,270 @@ + + */ +class RedirectPlugin implements Plugin +{ + /** + * Rule on how to redirect, change method for the new request. + * + * @var array + */ + protected $redirectCodes = [ + 300 => [ + 'switch' => [ + 'unless' => ['GET', 'HEAD'], + 'to' => 'GET', + ], + 'multiple' => true, + 'permanent' => false, + ], + 301 => [ + 'switch' => [ + 'unless' => ['GET', 'HEAD'], + 'to' => 'GET', + ], + 'multiple' => false, + 'permanent' => true, + ], + 302 => [ + 'switch' => [ + 'unless' => ['GET', 'HEAD'], + 'to' => 'GET', + ], + 'multiple' => false, + 'permanent' => false, + ], + 303 => [ + 'switch' => [ + 'unless' => ['GET', 'HEAD'], + 'to' => 'GET', + ], + 'multiple' => false, + 'permanent' => false, + ], + 307 => [ + 'switch' => false, + 'multiple' => false, + 'permanent' => false, + ], + 308 => [ + 'switch' => false, + 'multiple' => false, + 'permanent' => true, + ], + ]; + + /** + * Determine how header should be preserved from old request. + * + * @var bool|array + * + * true will keep all previous headers (default value) + * false will ditch all previous headers + * string[] will keep only headers with the specified names + */ + protected $preserveHeader; + + /** + * Store all previous redirect from 301 / 308 status code. + * + * @var array + */ + protected $redirectStorage = []; + + /** + * Whether the location header must be directly used for a multiple redirection status code (300). + * + * @var bool + */ + protected $useDefaultForMultiple; + + /** + * @var array + */ + protected $circularDetection = []; + + /** + * @param array $config { + * + * @var bool|string[] $preserve_header True keeps all headers, false remove all of them, an array is interpreted as a list of header names to keep + * @var bool $use_default_for_multiple Whether the location header must be directly used for a multiple redirection status code (300). + * } + */ + public function __construct(array $config = []) + { + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'preserve_header' => true, + 'use_default_for_multiple' => true, + ]); + $resolver->setAllowedTypes('preserve_header', ['bool', 'array']); + $resolver->setAllowedTypes('use_default_for_multiple', 'bool'); + $resolver->setNormalizer('preserve_header', function (OptionsResolver $resolver, $value) { + if (is_bool($value) && false === $value) { + return []; + } + + return $value; + }); + $options = $resolver->resolve($config); + + $this->preserveHeader = $options['preserve_header']; + $this->useDefaultForMultiple = $options['use_default_for_multiple']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + // Check in storage + if (array_key_exists((string) $request->getUri(), $this->redirectStorage)) { + $uri = $this->redirectStorage[(string) $request->getUri()]['uri']; + $statusCode = $this->redirectStorage[(string) $request->getUri()]['status']; + $redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode); + + return $first($redirectRequest); + } + + return $next($request)->then(function (ResponseInterface $response) use ($request, $first) { + $statusCode = $response->getStatusCode(); + + if (!array_key_exists($statusCode, $this->redirectCodes)) { + return $response; + } + + $uri = $this->createUri($response, $request); + $redirectRequest = $this->buildRedirectRequest($request, $uri, $statusCode); + $chainIdentifier = spl_object_hash((object) $first); + + if (!array_key_exists($chainIdentifier, $this->circularDetection)) { + $this->circularDetection[$chainIdentifier] = []; + } + + $this->circularDetection[$chainIdentifier][] = (string) $request->getUri(); + + if (in_array((string) $redirectRequest->getUri(), $this->circularDetection[$chainIdentifier])) { + throw new CircularRedirectionException('Circular redirection detected', $request, $response); + } + + if ($this->redirectCodes[$statusCode]['permanent']) { + $this->redirectStorage[(string) $request->getUri()] = [ + 'uri' => $uri, + 'status' => $statusCode, + ]; + } + + // Call redirect request in synchrone + $redirectPromise = $first($redirectRequest); + + return $redirectPromise->wait(); + }); + } + + /** + * Builds the redirect request. + * + * @param RequestInterface $request Original request + * @param UriInterface $uri New uri + * @param int $statusCode Status code from the redirect response + * + * @return MessageInterface|RequestInterface + */ + protected function buildRedirectRequest(RequestInterface $request, UriInterface $uri, $statusCode) + { + $request = $request->withUri($uri); + + if (false !== $this->redirectCodes[$statusCode]['switch'] && !in_array($request->getMethod(), $this->redirectCodes[$statusCode]['switch']['unless'])) { + $request = $request->withMethod($this->redirectCodes[$statusCode]['switch']['to']); + } + + if (is_array($this->preserveHeader)) { + $headers = array_keys($request->getHeaders()); + + foreach ($headers as $name) { + if (!in_array($name, $this->preserveHeader)) { + $request = $request->withoutHeader($name); + } + } + } + + return $request; + } + + /** + * Creates a new Uri from the old request and the location header. + * + * @param ResponseInterface $response The redirect response + * @param RequestInterface $request The original request + * + * @throws HttpException If location header is not usable (missing or incorrect) + * @throws MultipleRedirectionException If a 300 status code is received and default location cannot be resolved (doesn't use the location header or not present) + * + * @return UriInterface + */ + private function createUri(ResponseInterface $response, RequestInterface $request) + { + if ($this->redirectCodes[$response->getStatusCode()]['multiple'] && (!$this->useDefaultForMultiple || !$response->hasHeader('Location'))) { + throw new MultipleRedirectionException('Cannot choose a redirection', $request, $response); + } + + if (!$response->hasHeader('Location')) { + throw new HttpException('Redirect status code, but no location header present in the response', $request, $response); + } + + $location = $response->getHeaderLine('Location'); + $parsedLocation = parse_url($location); + + if (false === $parsedLocation) { + throw new HttpException(sprintf('Location %s could not be parsed', $location), $request, $response); + } + + $uri = $request->getUri(); + + if (array_key_exists('scheme', $parsedLocation)) { + $uri = $uri->withScheme($parsedLocation['scheme']); + } + + if (array_key_exists('host', $parsedLocation)) { + $uri = $uri->withHost($parsedLocation['host']); + } + + if (array_key_exists('port', $parsedLocation)) { + $uri = $uri->withPort($parsedLocation['port']); + } + + if (array_key_exists('path', $parsedLocation)) { + $uri = $uri->withPath($parsedLocation['path']); + } + + if (array_key_exists('query', $parsedLocation)) { + $uri = $uri->withQuery($parsedLocation['query']); + } else { + $uri = $uri->withQuery(''); + } + + if (array_key_exists('fragment', $parsedLocation)) { + $uri = $uri->withFragment($parsedLocation['fragment']); + } else { + $uri = $uri->withFragment(''); + } + + return $uri; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php new file mode 100644 index 0000000..5f72b02 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/RequestMatcherPlugin.php @@ -0,0 +1,47 @@ + + */ +final class RequestMatcherPlugin implements Plugin +{ + /** + * @var RequestMatcher + */ + private $requestMatcher; + + /** + * @var Plugin + */ + private $delegatedPlugin; + + /** + * @param RequestMatcher $requestMatcher + * @param Plugin $delegatedPlugin + */ + public function __construct(RequestMatcher $requestMatcher, Plugin $delegatedPlugin) + { + $this->requestMatcher = $requestMatcher; + $this->delegatedPlugin = $delegatedPlugin; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + if ($this->requestMatcher->matches($request)) { + return $this->delegatedPlugin->handleRequest($request, $next, $first); + } + + return $next($request); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/RetryPlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/RetryPlugin.php new file mode 100644 index 0000000..3d09265 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/RetryPlugin.php @@ -0,0 +1,139 @@ + + */ +final class RetryPlugin implements Plugin +{ + /** + * Number of retry before sending an exception. + * + * @var int + */ + private $retry; + + /** + * @var callable + */ + private $exceptionDelay; + + /** + * @var callable + */ + private $exceptionDecider; + + /** + * Store the retry counter for each request. + * + * @var array + */ + private $retryStorage = []; + + /** + * @param array $config { + * + * @var int $retries Number of retries to attempt if an exception occurs before letting the exception bubble up. + * @var callable $exception_decider A callback that gets a request and an exception to decide after a failure whether the request should be retried. + * @var callable $exception_delay A callback that gets a request, an exception and the number of retries and returns how many microseconds we should wait before trying again. + * } + */ + public function __construct(array $config = []) + { + if (array_key_exists('decider', $config)) { + if (array_key_exists('exception_decider', $config)) { + throw new \InvalidArgumentException('Do not set both the old "decider" and new "exception_decider" options'); + } + trigger_error('The "decider" option has been deprecated in favour of "exception_decider"', E_USER_DEPRECATED); + $config['exception_decider'] = $config['decider']; + unset($config['decider']); + } + if (array_key_exists('delay', $config)) { + if (array_key_exists('exception_delay', $config)) { + throw new \InvalidArgumentException('Do not set both the old "delay" and new "exception_delay" options'); + } + trigger_error('The "delay" option has been deprecated in favour of "exception_delay"', E_USER_DEPRECATED); + $config['exception_delay'] = $config['delay']; + unset($config['delay']); + } + + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'retries' => 1, + 'exception_decider' => function (RequestInterface $request, Exception $e) { + return true; + }, + 'exception_delay' => __CLASS__.'::defaultDelay', + ]); + $resolver->setAllowedTypes('retries', 'int'); + $resolver->setAllowedTypes('exception_decider', 'callable'); + $resolver->setAllowedTypes('exception_delay', 'callable'); + $options = $resolver->resolve($config); + + $this->retry = $options['retries']; + $this->exceptionDecider = $options['exception_decider']; + $this->exceptionDelay = $options['exception_delay']; + } + + /** + * {@inheritdoc} + */ + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + $chainIdentifier = spl_object_hash((object) $first); + + return $next($request)->then(function (ResponseInterface $response) use ($request, $chainIdentifier) { + if (array_key_exists($chainIdentifier, $this->retryStorage)) { + unset($this->retryStorage[$chainIdentifier]); + } + + return $response; + }, function (Exception $exception) use ($request, $next, $first, $chainIdentifier) { + if (!array_key_exists($chainIdentifier, $this->retryStorage)) { + $this->retryStorage[$chainIdentifier] = 0; + } + + if ($this->retryStorage[$chainIdentifier] >= $this->retry) { + unset($this->retryStorage[$chainIdentifier]); + + throw $exception; + } + + if (!call_user_func($this->exceptionDecider, $request, $exception)) { + throw $exception; + } + + $time = call_user_func($this->exceptionDelay, $request, $exception, $this->retryStorage[$chainIdentifier]); + usleep($time); + + // Retry in synchrone + ++$this->retryStorage[$chainIdentifier]; + $promise = $this->handleRequest($request, $next, $first); + + return $promise->wait(); + }); + } + + /** + * @param RequestInterface $request + * @param Exception $e + * @param int $retries The number of retries we made before. First time this get called it will be 0. + * + * @return int + */ + public static function defaultDelay(RequestInterface $request, Exception $e, $retries) + { + return pow(2, $retries) * 500000; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/Plugin/VersionBridgePlugin.php b/www/multitube/vendor/php-http/client-common/src/Plugin/VersionBridgePlugin.php new file mode 100644 index 0000000..f3891e5 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/Plugin/VersionBridgePlugin.php @@ -0,0 +1,21 @@ + + */ +trait VersionBridgePlugin +{ + abstract protected function doHandleRequest(RequestInterface $request, callable $next, callable $first); + + public function handleRequest(RequestInterface $request, callable $next, callable $first) + { + return $this->doHandleRequest($request, $next, $first); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/PluginClient.php b/www/multitube/vendor/php-http/client-common/src/PluginClient.php new file mode 100644 index 0000000..625033b --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/PluginClient.php @@ -0,0 +1,180 @@ + + */ +final class PluginClient implements HttpClient, HttpAsyncClient +{ + /** + * An HTTP async client. + * + * @var HttpAsyncClient + */ + private $client; + + /** + * The plugin chain. + * + * @var Plugin[] + */ + private $plugins; + + /** + * A list of options. + * + * @var array + */ + private $options; + + /** + * @param HttpClient|HttpAsyncClient|ClientInterface $client + * @param Plugin[] $plugins + * @param array $options { + * + * @var int $max_restarts + * @var Plugin[] $debug_plugins an array of plugins that are injected between each normal plugin + * } + * + * @throws \RuntimeException if client is not an instance of HttpClient or HttpAsyncClient + */ + public function __construct($client, array $plugins = [], array $options = []) + { + if ($client instanceof HttpAsyncClient) { + $this->client = $client; + } elseif ($client instanceof HttpClient || $client instanceof ClientInterface) { + $this->client = new EmulatedHttpAsyncClient($client); + } else { + throw new \RuntimeException('Client must be an instance of Http\\Client\\HttpClient or Http\\Client\\HttpAsyncClient'); + } + + $this->plugins = $plugins; + $this->options = $this->configure($options); + } + + /** + * {@inheritdoc} + */ + public function sendRequest(RequestInterface $request) + { + // If we don't have an http client, use the async call + if (!($this->client instanceof HttpClient)) { + return $this->sendAsyncRequest($request)->wait(); + } + + // Else we want to use the synchronous call of the underlying client, and not the async one in the case + // we have both an async and sync call + $pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) { + try { + return new HttpFulfilledPromise($this->client->sendRequest($request)); + } catch (HttplugException $exception) { + return new HttpRejectedPromise($exception); + } + }); + + return $pluginChain($request)->wait(); + } + + /** + * {@inheritdoc} + */ + public function sendAsyncRequest(RequestInterface $request) + { + $pluginChain = $this->createPluginChain($this->plugins, function (RequestInterface $request) { + return $this->client->sendAsyncRequest($request); + }); + + return $pluginChain($request); + } + + /** + * Configure the plugin client. + * + * @param array $options + * + * @return array + */ + private function configure(array $options = []) + { + if (isset($options['debug_plugins'])) { + @trigger_error('The "debug_plugins" option is deprecated since 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); + } + + $resolver = new OptionsResolver(); + $resolver->setDefaults([ + 'max_restarts' => 10, + 'debug_plugins' => [], + ]); + + $resolver + ->setAllowedTypes('debug_plugins', 'array') + ->setAllowedValues('debug_plugins', function (array $plugins) { + foreach ($plugins as $plugin) { + // Make sure each object passed with the `debug_plugins` is an instance of Plugin. + if (!$plugin instanceof Plugin) { + return false; + } + } + + return true; + }); + + return $resolver->resolve($options); + } + + /** + * Create the plugin chain. + * + * @param Plugin[] $pluginList A list of plugins + * @param callable $clientCallable Callable making the HTTP call + * + * @return callable + */ + private function createPluginChain($pluginList, callable $clientCallable) + { + $firstCallable = $lastCallable = $clientCallable; + + /* + * Inject debug plugins between each plugin. + */ + $pluginListWithDebug = $this->options['debug_plugins']; + foreach ($pluginList as $plugin) { + $pluginListWithDebug[] = $plugin; + $pluginListWithDebug = array_merge($pluginListWithDebug, $this->options['debug_plugins']); + } + + while ($plugin = array_pop($pluginListWithDebug)) { + $lastCallable = function (RequestInterface $request) use ($plugin, $lastCallable, &$firstCallable) { + return $plugin->handleRequest($request, $lastCallable, $firstCallable); + }; + + $firstCallable = $lastCallable; + } + + $firstCalls = 0; + $firstCallable = function (RequestInterface $request) use ($lastCallable, &$firstCalls) { + if ($firstCalls > $this->options['max_restarts']) { + throw new LoopException('Too many restarts in plugin client', $request); + } + + ++$firstCalls; + + return $lastCallable($request); + }; + + return $firstCallable; + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/PluginClientFactory.php b/www/multitube/vendor/php-http/client-common/src/PluginClientFactory.php new file mode 100644 index 0000000..cbea3e1 --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/PluginClientFactory.php @@ -0,0 +1,63 @@ + + */ +final class PluginClientFactory +{ + /** + * @var callable + */ + private static $factory; + + /** + * Set the factory to use. + * The callable to provide must have the same arguments and return type as PluginClientFactory::createClient. + * This is used by the HTTPlugBundle to provide a better Symfony integration. + * Unlike the createClient method, this one is static to allow zero configuration profiling by hooking into early + * application execution. + * + * @internal + * + * @param callable $factory + */ + public static function setFactory(callable $factory) + { + static::$factory = $factory; + } + + /** + * @param HttpClient|HttpAsyncClient|ClientInterface $client + * @param Plugin[] $plugins + * @param array $options { + * + * @var string $client_name to give client a name which may be used when displaying client information like in + * the HTTPlugBundle profiler. + * } + * + * @see PluginClient constructor for PluginClient specific $options. + * + * @return PluginClient + */ + public function createClient($client, array $plugins = [], array $options = []) + { + if (static::$factory) { + $factory = static::$factory; + + return $factory($client, $plugins, $options); + } + + unset($options['client_name']); + + return new PluginClient($client, $plugins, $options); + } +} diff --git a/www/multitube/vendor/php-http/client-common/src/VersionBridgeClient.php b/www/multitube/vendor/php-http/client-common/src/VersionBridgeClient.php new file mode 100644 index 0000000..048eeae --- /dev/null +++ b/www/multitube/vendor/php-http/client-common/src/VersionBridgeClient.php @@ -0,0 +1,21 @@ + + */ +trait VersionBridgeClient +{ + abstract protected function doSendRequest(RequestInterface $request); + + public function sendRequest(RequestInterface $request) + { + return $this->doSendRequest($request); + } +} diff --git a/www/multitube/vendor/php-http/discovery/CHANGELOG.md b/www/multitube/vendor/php-http/discovery/CHANGELOG.md new file mode 100644 index 0000000..94e1a64 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/CHANGELOG.md @@ -0,0 +1,307 @@ +# Change Log + +## 1.13.0 - 2020-11-27 + +- Support discovering PSR-17 factories of `slim/psr7` package https://github.com/php-http/discovery/pull/192 + +## 1.12.0 - 2020-09-22 + +- Support discovering HttpClient of `php-http/guzzle7-adapter` https://github.com/php-http/discovery/pull/189 + +## 1.11.0 - 2020-09-22 + +- Use correct method name to find Uri Factory in PSR17 https://github.com/php-http/discovery/pull/181 + +## 1.10.0 - 2020-09-04 + +- Discover PSR-18 implementation of phalcon + +## 1.9.1 - 2020-07-13 + +### Fixed + +- Support PHP 7.4 and 8.0 + +## 1.9.0 - 2020-07-02 + +### Added + +- Support discovering PSR-18 factories of `guzzlehttp/guzzle` 7+ + +## 1.8.0 - 2020-06-14 + +### Added + +- Support discovering PSR-17 factories of `guzzlehttp/psr7` package +- Support discovering PSR-17 factories of `laminas/laminas-diactoros` package +- `ClassDiscovery::getStrategies()` to retrieve the list of current strategies. + +### Fixed + +- Ignore exception during discovery when Symfony HttplugClient checks if HTTPlug is available. + +## 1.7.4 - 2020-01-03 + +### Fixed + +- Improve conditions on Symfony's async HTTPlug client. + +## 1.7.3 - 2019-12-27 + +### Fixed + +- Enough conditions to only use Symfony HTTP client if all needed components are available. + +## 1.7.2 - 2019-12-27 + +### Fixed + +- Allow a condition to specify an interface and not just classes. + +## 1.7.1 - 2019-12-26 + +### Fixed + +- Better conditions to see if Symfony's HTTP clients are available. + +## 1.7.0 - 2019-06-30 + +### Added + +- Dropped support for PHP < 7.1 +- Support for `symfony/http-client` + +## 1.6.1 - 2019-02-23 + +### Fixed + +- MockClientStrategy also provides the mock client when requesting an async client + +## 1.6.0 - 2019-01-23 + +### Added + +- Support for PSR-17 factories +- Support for PSR-18 clients + +## 1.5.2 - 2018-12-31 + +Corrected mistakes in 1.5.1. The different between 1.5.2 and 1.5.0 is that +we removed some PHP 7 code. + +https://github.com/php-http/discovery/compare/1.5.0...1.5.2 + +## 1.5.1 - 2018-12-31 + +This version added new features by mistake. These are reverted in 1.5.2. + +Do not use 1.5.1. + +### Fixed + +- Removed PHP 7 code + +## 1.5.0 - 2018-12-30 + +### Added + +- Support for `nyholm/psr7` version 1.0. +- `ClassDiscovery::safeClassExists` which will help Magento users. +- Support for HTTPlug 2.0 +- Support for Buzz 1.0 +- Better error message when nothing found by introducing a new exception: `NoCandidateFoundException`. + +### Fixed + +- Fixed condition evaluation, it should stop after first invalid condition. + +## 1.4.0 - 2018-02-06 + +### Added + +- Discovery support for nyholm/psr7 + +## 1.3.0 - 2017-08-03 + +### Added + +- Discovery support for CakePHP adapter +- Discovery support for Zend adapter +- Discovery support for Artax adapter + +## 1.2.1 - 2017-03-02 + +### Fixed + +- Fixed minor issue with `MockClientStrategy`, also added more tests. + +## 1.2.0 - 2017-02-12 + +### Added + +- MockClientStrategy class. + +## 1.1.1 - 2016-11-27 + +### Changed + +- Made exception messages clearer. `StrategyUnavailableException` is no longer the previous exception to `DiscoveryFailedException`. +- `CommonClassesStrategy` is using `self` instead of `static`. Using `static` makes no sense when `CommonClassesStrategy` is final. + +## 1.1.0 - 2016-10-20 + +### Added + +- Discovery support for Slim Framework factories + +## 1.0.0 - 2016-07-18 + +### Added + +- Added back `Http\Discovery\NotFoundException` to preserve BC with 0.8 version. You may upgrade from 0.8.x and 0.9.x to 1.0.0 without any BC breaks. +- Added interface `Http\Discovery\Exception` which is implemented by all our exceptions + +### Changed + +- Puli strategy renamed to Puli Beta strategy to prevent incompatibility with a future Puli stable + +### Deprecated + +- For BC reasons, the old `Http\Discovery\NotFoundException` (extending the new exception) will be thrown until version 2.0 + + +## 0.9.1 - 2016-06-28 + +### Changed + +- Dropping PHP 5.4 support because we use the ::class constant. + + +## 0.9.0 - 2016-06-25 + +### Added + +- Discovery strategies to find classes + +### Changed + +- [Puli](http://puli.io) made optional +- Improved exceptions +- **[BC] `NotFoundException` moved to `Http\Discovery\Exception\NotFoundException`** + + +## 0.8.0 - 2016-02-11 + +### Changed + +- Puli composer plugin must be installed separately + + +## 0.7.0 - 2016-01-15 + +### Added + +- Temporary puli.phar (Beta 10) executable + +### Changed + +- Updated HTTPlug dependencies +- Updated Puli dependencies +- Local configuration to make tests passing + +### Removed + +- Puli CLI dependency + + +## 0.6.4 - 2016-01-07 + +### Fixed + +- Puli [not working](https://twitter.com/PuliPHP/status/685132540588507137) with the latest json-schema + + +## 0.6.3 - 2016-01-04 + +### Changed + +- Adjust Puli dependencies + + +## 0.6.2 - 2016-01-04 + +### Changed + +- Make Puli CLI a requirement + + +## 0.6.1 - 2016-01-03 + +### Changed + +- More flexible Puli requirement + + +## 0.6.0 - 2015-12-30 + +### Changed + +- Use [Puli](http://puli.io) for discovery +- Improved exception messages + + +## 0.5.0 - 2015-12-25 + +### Changed + +- Updated message factory dependency (php-http/message) + + +## 0.4.0 - 2015-12-17 + +### Added + +- Array condition evaluation in the Class Discovery + +### Removed + +- Message factories (moved to php-http/utils) + + +## 0.3.0 - 2015-11-18 + +### Added + +- HTTP Async Client Discovery +- Stream factories + +### Changed + +- Discoveries and Factories are final +- Message and Uri factories have the type in their names +- Diactoros Message factory uses Stream factory internally + +### Fixed + +- Improved docblocks for API documentation generation + + +## 0.2.0 - 2015-10-31 + +### Changed + +- Renamed AdapterDiscovery to ClientDiscovery + + +## 0.1.1 - 2015-06-13 + +### Fixed + +- Bad HTTP Adapter class name for Guzzle 5 + + +## 0.1.0 - 2015-06-12 + +### Added + +- Initial release diff --git a/www/multitube/vendor/php-http/discovery/LICENSE b/www/multitube/vendor/php-http/discovery/LICENSE new file mode 100644 index 0000000..4558d6f --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2016 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/discovery/README.md b/www/multitube/vendor/php-http/discovery/README.md new file mode 100644 index 0000000..6a3d18b --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/README.md @@ -0,0 +1,46 @@ +# HTTPlug Discovery + +[![Latest Version](https://img.shields.io/github/release/php-http/discovery.svg?style=flat-square)](https://github.com/php-http/discovery/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/travis/php-http/discovery/master.svg?style=flat-square)](https://travis-ci.org/php-http/discovery) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/discovery.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/discovery) +[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/discovery.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/discovery) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/discovery.svg?style=flat-square)](https://packagist.org/packages/php-http/discovery) + +**Finds installed HTTPlug implementations and PSR-7 message factories.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/discovery +``` + + +## Documentation + +Please see the [official documentation](http://php-http.readthedocs.org/en/latest/discovery.html). + + +## Testing + +``` bash +$ composer test +``` + + +## Contributing + +Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html). + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/discovery/composer.json b/www/multitube/vendor/php-http/discovery/composer.json new file mode 100644 index 0000000..3a8cc7c --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/composer.json @@ -0,0 +1,51 @@ +{ + "name": "php-http/discovery", + "description": "Finds installed HTTPlug implementations and PSR-7 message factories", + "license": "MIT", + "keywords": ["http", "discovery", "client", "adapter", "message", "factory", "psr7"], + "homepage": "http://php-http.org", + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "graham-campbell/phpspec-skip-example-extension": "^5.0", + "php-http/httplug": "^1.0 || ^2.0", + "php-http/message-factory": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.1", + "puli/composer-plugin": "1.0.0-beta10" + }, + "suggest": { + "puli/composer-plugin": "Sets up Puli which is recommended for Discovery to work. Check http://docs.php-http.org/en/latest/discovery.html for more details.", + "php-http/message": "Allow to use Guzzle, Diactoros or Slim Framework factories" + }, + "autoload": { + "psr-4": { + "Http\\Discovery\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "spec\\Http\\Discovery\\": "spec/" + } + }, + "scripts": { + "test": "vendor/bin/phpspec run", + "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" + }, + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "conflict": { + "nyholm/psr7": "<1.0" + }, + "prefer-stable": true, + "minimum-stability": "beta" +} diff --git a/www/multitube/vendor/php-http/discovery/src/ClassDiscovery.php b/www/multitube/vendor/php-http/discovery/src/ClassDiscovery.php new file mode 100644 index 0000000..ee280f3 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/ClassDiscovery.php @@ -0,0 +1,246 @@ + + * @author Márk Sági-Kazár + * @author Tobias Nyholm + */ +abstract class ClassDiscovery +{ + /** + * A list of strategies to find classes. + * + * @var array + */ + private static $strategies = [ + Strategy\PuliBetaStrategy::class, + Strategy\CommonClassesStrategy::class, + Strategy\CommonPsr17ClassesStrategy::class, + ]; + + /** + * Discovery cache to make the second time we use discovery faster. + * + * @var array + */ + private static $cache = []; + + /** + * Finds a class. + * + * @param string $type + * + * @return string|\Closure + * + * @throws DiscoveryFailedException + */ + protected static function findOneByType($type) + { + // Look in the cache + if (null !== ($class = self::getFromCache($type))) { + return $class; + } + + $exceptions = []; + foreach (self::$strategies as $strategy) { + try { + $candidates = call_user_func($strategy.'::getCandidates', $type); + } catch (StrategyUnavailableException $e) { + $exceptions[] = $e; + + continue; + } + + foreach ($candidates as $candidate) { + if (isset($candidate['condition'])) { + if (!self::evaluateCondition($candidate['condition'])) { + continue; + } + } + + // save the result for later use + self::storeInCache($type, $candidate); + + return $candidate['class']; + } + + $exceptions[] = new NoCandidateFoundException($strategy, $candidates); + } + + throw DiscoveryFailedException::create($exceptions); + } + + /** + * Get a value from cache. + * + * @param string $type + * + * @return string|null + */ + private static function getFromCache($type) + { + if (!isset(self::$cache[$type])) { + return; + } + + $candidate = self::$cache[$type]; + if (isset($candidate['condition'])) { + if (!self::evaluateCondition($candidate['condition'])) { + return; + } + } + + return $candidate['class']; + } + + /** + * Store a value in cache. + * + * @param string $type + * @param string $class + */ + private static function storeInCache($type, $class) + { + self::$cache[$type] = $class; + } + + /** + * Set new strategies and clear the cache. + * + * @param array $strategies string array of fully qualified class name to a DiscoveryStrategy + */ + public static function setStrategies(array $strategies) + { + self::$strategies = $strategies; + self::clearCache(); + } + + /** + * Returns the currently configured discovery strategies as fully qualified class names. + * + * @return string[] + */ + public static function getStrategies(): iterable + { + return self::$strategies; + } + + /** + * Append a strategy at the end of the strategy queue. + * + * @param string $strategy Fully qualified class name to a DiscoveryStrategy + */ + public static function appendStrategy($strategy) + { + self::$strategies[] = $strategy; + self::clearCache(); + } + + /** + * Prepend a strategy at the beginning of the strategy queue. + * + * @param string $strategy Fully qualified class name to a DiscoveryStrategy + */ + public static function prependStrategy($strategy) + { + array_unshift(self::$strategies, $strategy); + self::clearCache(); + } + + /** + * Clear the cache. + */ + public static function clearCache() + { + self::$cache = []; + } + + /** + * Evaluates conditions to boolean. + * + * @param mixed $condition + * + * @return bool + */ + protected static function evaluateCondition($condition) + { + if (is_string($condition)) { + // Should be extended for functions, extensions??? + return self::safeClassExists($condition); + } + if (is_callable($condition)) { + return (bool) $condition(); + } + if (is_bool($condition)) { + return $condition; + } + if (is_array($condition)) { + foreach ($condition as $c) { + if (false === static::evaluateCondition($c)) { + // Immediately stop execution if the condition is false + return false; + } + } + + return true; + } + + return false; + } + + /** + * Get an instance of the $class. + * + * @param string|\Closure $class A FQCN of a class or a closure that instantiate the class. + * + * @return object + * + * @throws ClassInstantiationFailedException + */ + protected static function instantiateClass($class) + { + try { + if (is_string($class)) { + return new $class(); + } + + if (is_callable($class)) { + return $class(); + } + } catch (\Exception $e) { + throw new ClassInstantiationFailedException('Unexpected exception when instantiating class.', 0, $e); + } + + throw new ClassInstantiationFailedException('Could not instantiate class because parameter is neither a callable nor a string'); + } + + /** + * We want to do a "safe" version of PHP's "class_exists" because Magento has a bug + * (or they call it a "feature"). Magento is throwing an exception if you do class_exists() + * on a class that ends with "Factory" and if that file does not exits. + * + * This function will catch all potential exceptions and make sure it returns a boolean. + * + * @param string $class + * @param bool $autoload + * + * @return bool + */ + public static function safeClassExists($class) + { + try { + return class_exists($class) || interface_exists($class); + } catch (\Exception $e) { + return false; + } + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception.php b/www/multitube/vendor/php-http/discovery/src/Exception.php new file mode 100644 index 0000000..973c908 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception.php @@ -0,0 +1,12 @@ + + */ +interface Exception +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/ClassInstantiationFailedException.php b/www/multitube/vendor/php-http/discovery/src/Exception/ClassInstantiationFailedException.php new file mode 100644 index 0000000..e95bf5d --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/ClassInstantiationFailedException.php @@ -0,0 +1,14 @@ + + */ +final class ClassInstantiationFailedException extends \RuntimeException implements Exception +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/DiscoveryFailedException.php b/www/multitube/vendor/php-http/discovery/src/Exception/DiscoveryFailedException.php new file mode 100644 index 0000000..304b727 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/DiscoveryFailedException.php @@ -0,0 +1,51 @@ + + */ +final class DiscoveryFailedException extends \Exception implements Exception +{ + /** + * @var \Exception[] + */ + private $exceptions; + + /** + * @param string $message + * @param \Exception[] $exceptions + */ + public function __construct($message, array $exceptions = []) + { + $this->exceptions = $exceptions; + + parent::__construct($message); + } + + /** + * @param \Exception[] $exceptions + */ + public static function create($exceptions) + { + $message = 'Could not find resource using any discovery strategy. Find more information at http://docs.php-http.org/en/latest/discovery.html#common-errors'; + foreach ($exceptions as $e) { + $message .= "\n - ".$e->getMessage(); + } + $message .= "\n\n"; + + return new self($message, $exceptions); + } + + /** + * @return \Exception[] + */ + public function getExceptions() + { + return $this->exceptions; + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/NoCandidateFoundException.php b/www/multitube/vendor/php-http/discovery/src/Exception/NoCandidateFoundException.php new file mode 100644 index 0000000..32f65db --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/NoCandidateFoundException.php @@ -0,0 +1,47 @@ + + */ +final class NoCandidateFoundException extends \Exception implements Exception +{ + /** + * @param string $strategy + */ + public function __construct($strategy, array $candidates) + { + $classes = array_map( + function ($a) { + return $a['class']; + }, + $candidates + ); + + $message = sprintf( + 'No valid candidate found using strategy "%s". We tested the following candidates: %s.', + $strategy, + implode(', ', array_map([$this, 'stringify'], $classes)) + ); + + parent::__construct($message); + } + + private function stringify($mixed) + { + if (is_string($mixed)) { + return $mixed; + } + + if (is_array($mixed) && 2 === count($mixed)) { + return sprintf('%s::%s', $this->stringify($mixed[0]), $mixed[1]); + } + + return is_object($mixed) ? get_class($mixed) : gettype($mixed); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/NotFoundException.php b/www/multitube/vendor/php-http/discovery/src/Exception/NotFoundException.php new file mode 100644 index 0000000..befbf48 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/NotFoundException.php @@ -0,0 +1,16 @@ + + */ +/*final */class NotFoundException extends \RuntimeException implements Exception +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/PuliUnavailableException.php b/www/multitube/vendor/php-http/discovery/src/Exception/PuliUnavailableException.php new file mode 100644 index 0000000..a6ade73 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/PuliUnavailableException.php @@ -0,0 +1,12 @@ + + */ +final class PuliUnavailableException extends StrategyUnavailableException +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/Exception/StrategyUnavailableException.php b/www/multitube/vendor/php-http/discovery/src/Exception/StrategyUnavailableException.php new file mode 100644 index 0000000..89ecf35 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Exception/StrategyUnavailableException.php @@ -0,0 +1,15 @@ + + */ +class StrategyUnavailableException extends \RuntimeException implements Exception +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/HttpAsyncClientDiscovery.php b/www/multitube/vendor/php-http/discovery/src/HttpAsyncClientDiscovery.php new file mode 100644 index 0000000..a0c4d5b --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/HttpAsyncClientDiscovery.php @@ -0,0 +1,32 @@ + + */ +final class HttpAsyncClientDiscovery extends ClassDiscovery +{ + /** + * Finds an HTTP Async Client. + * + * @return HttpAsyncClient + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $asyncClient = static::findOneByType(HttpAsyncClient::class); + } catch (DiscoveryFailedException $e) { + throw new NotFoundException('No HTTPlug async clients found. Make sure to install a package providing "php-http/async-client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e); + } + + return static::instantiateClass($asyncClient); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/HttpClientDiscovery.php b/www/multitube/vendor/php-http/discovery/src/HttpClientDiscovery.php new file mode 100644 index 0000000..2072b94 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/HttpClientDiscovery.php @@ -0,0 +1,32 @@ + + */ +final class HttpClientDiscovery extends ClassDiscovery +{ + /** + * Finds an HTTP Client. + * + * @return HttpClient + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $client = static::findOneByType(HttpClient::class); + } catch (DiscoveryFailedException $e) { + throw new NotFoundException('No HTTPlug clients found. Make sure to install a package providing "php-http/client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e); + } + + return static::instantiateClass($client); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/MessageFactoryDiscovery.php b/www/multitube/vendor/php-http/discovery/src/MessageFactoryDiscovery.php new file mode 100644 index 0000000..659916d --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/MessageFactoryDiscovery.php @@ -0,0 +1,34 @@ + + * + * @deprecated This will be removed in 2.0. Consider using Psr17FactoryDiscovery. + */ +final class MessageFactoryDiscovery extends ClassDiscovery +{ + /** + * Finds a Message Factory. + * + * @return MessageFactory + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $messageFactory = static::findOneByType(MessageFactory::class); + } catch (DiscoveryFailedException $e) { + throw new NotFoundException('No message factories found. To use Guzzle, Diactoros or Slim Framework factories install php-http/message and the chosen message implementation.', 0, $e); + } + + return static::instantiateClass($messageFactory); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/NotFoundException.php b/www/multitube/vendor/php-http/discovery/src/NotFoundException.php new file mode 100644 index 0000000..d59dadb --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/NotFoundException.php @@ -0,0 +1,14 @@ + + * + * @deprecated since since version 1.0, and will be removed in 2.0. Use {@link \Http\Discovery\Exception\NotFoundException} instead. + */ +final class NotFoundException extends \Http\Discovery\Exception\NotFoundException +{ +} diff --git a/www/multitube/vendor/php-http/discovery/src/Psr17FactoryDiscovery.php b/www/multitube/vendor/php-http/discovery/src/Psr17FactoryDiscovery.php new file mode 100644 index 0000000..a73c641 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Psr17FactoryDiscovery.php @@ -0,0 +1,136 @@ + + */ +final class Psr17FactoryDiscovery extends ClassDiscovery +{ + private static function createException($type, Exception $e) + { + return new \Http\Discovery\Exception\NotFoundException( + 'No PSR-17 '.$type.' found. Install a package from this list: https://packagist.org/providers/psr/http-factory-implementation', + 0, + $e + ); + } + + /** + * @return RequestFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findRequestFactory() + { + try { + $messageFactory = static::findOneByType(RequestFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('request factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return ResponseFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findResponseFactory() + { + try { + $messageFactory = static::findOneByType(ResponseFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('response factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return ServerRequestFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findServerRequestFactory() + { + try { + $messageFactory = static::findOneByType(ServerRequestFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('server request factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return StreamFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findStreamFactory() + { + try { + $messageFactory = static::findOneByType(StreamFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('stream factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return UploadedFileFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findUploadedFileFactory() + { + try { + $messageFactory = static::findOneByType(UploadedFileFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('uploaded file factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return UriFactoryInterface + * + * @throws Exception\NotFoundException + */ + public static function findUriFactory() + { + try { + $messageFactory = static::findOneByType(UriFactoryInterface::class); + } catch (DiscoveryFailedException $e) { + throw self::createException('url factory', $e); + } + + return static::instantiateClass($messageFactory); + } + + /** + * @return UriFactoryInterface + * + * @throws Exception\NotFoundException + * + * @deprecated This will be removed in 2.0. Consider using the findUriFactory() method. + */ + public static function findUrlFactory() + { + return static::findUriFactory(); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Psr18ClientDiscovery.php b/www/multitube/vendor/php-http/discovery/src/Psr18ClientDiscovery.php new file mode 100644 index 0000000..7fcdb17 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Psr18ClientDiscovery.php @@ -0,0 +1,32 @@ + + */ +final class Psr18ClientDiscovery extends ClassDiscovery +{ + /** + * Finds a PSR-18 HTTP Client. + * + * @return ClientInterface + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $client = static::findOneByType(ClientInterface::class); + } catch (DiscoveryFailedException $e) { + throw new \Http\Discovery\Exception\NotFoundException('No PSR-18 clients found. Make sure to install a package providing "psr/http-client-implementation". Example: "php-http/guzzle6-adapter".', 0, $e); + } + + return static::instantiateClass($client); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Strategy/CommonClassesStrategy.php b/www/multitube/vendor/php-http/discovery/src/Strategy/CommonClassesStrategy.php new file mode 100644 index 0000000..0137c91 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Strategy/CommonClassesStrategy.php @@ -0,0 +1,181 @@ + + */ +final class CommonClassesStrategy implements DiscoveryStrategy +{ + /** + * @var array + */ + private static $classes = [ + MessageFactory::class => [ + ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]], + ['class' => GuzzleMessageFactory::class, 'condition' => [GuzzleRequest::class, GuzzleMessageFactory::class]], + ['class' => DiactorosMessageFactory::class, 'condition' => [DiactorosRequest::class, DiactorosMessageFactory::class]], + ['class' => SlimMessageFactory::class, 'condition' => [SlimRequest::class, SlimMessageFactory::class]], + ], + StreamFactory::class => [ + ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]], + ['class' => GuzzleStreamFactory::class, 'condition' => [GuzzleRequest::class, GuzzleStreamFactory::class]], + ['class' => DiactorosStreamFactory::class, 'condition' => [DiactorosRequest::class, DiactorosStreamFactory::class]], + ['class' => SlimStreamFactory::class, 'condition' => [SlimRequest::class, SlimStreamFactory::class]], + ], + UriFactory::class => [ + ['class' => NyholmHttplugFactory::class, 'condition' => [NyholmHttplugFactory::class]], + ['class' => GuzzleUriFactory::class, 'condition' => [GuzzleRequest::class, GuzzleUriFactory::class]], + ['class' => DiactorosUriFactory::class, 'condition' => [DiactorosRequest::class, DiactorosUriFactory::class]], + ['class' => SlimUriFactory::class, 'condition' => [SlimRequest::class, SlimUriFactory::class]], + ], + HttpAsyncClient::class => [ + ['class' => SymfonyHttplug::class, 'condition' => [SymfonyHttplug::class, Promise::class, RequestFactory::class, [self::class, 'isPsr17FactoryInstalled']]], + ['class' => Guzzle7::class, 'condition' => Guzzle7::class], + ['class' => Guzzle6::class, 'condition' => Guzzle6::class], + ['class' => Curl::class, 'condition' => Curl::class], + ['class' => React::class, 'condition' => React::class], + ], + HttpClient::class => [ + ['class' => SymfonyHttplug::class, 'condition' => [SymfonyHttplug::class, RequestFactory::class, [self::class, 'isPsr17FactoryInstalled']]], + ['class' => Guzzle7::class, 'condition' => Guzzle7::class], + ['class' => Guzzle6::class, 'condition' => Guzzle6::class], + ['class' => Guzzle5::class, 'condition' => Guzzle5::class], + ['class' => Curl::class, 'condition' => Curl::class], + ['class' => Socket::class, 'condition' => Socket::class], + ['class' => Buzz::class, 'condition' => Buzz::class], + ['class' => React::class, 'condition' => React::class], + ['class' => Cake::class, 'condition' => Cake::class], + ['class' => Zend::class, 'condition' => Zend::class], + ['class' => Artax::class, 'condition' => Artax::class], + [ + 'class' => [self::class, 'buzzInstantiate'], + 'condition' => [\Buzz\Client\FileGetContents::class, \Buzz\Message\ResponseBuilder::class], + ], + ], + Psr18Client::class => [ + [ + 'class' => [self::class, 'symfonyPsr18Instantiate'], + 'condition' => [SymfonyPsr18::class, Psr17RequestFactory::class], + ], + [ + 'class' => GuzzleHttp::class, + 'condition' => [self::class, 'isGuzzleImplementingPsr18'], + ], + [ + 'class' => [self::class, 'buzzInstantiate'], + 'condition' => [\Buzz\Client\FileGetContents::class, \Buzz\Message\ResponseBuilder::class], + ], + ], + ]; + + /** + * {@inheritdoc} + */ + public static function getCandidates($type) + { + if (Psr18Client::class === $type) { + return self::getPsr18Candidates(); + } + + return self::$classes[$type] ?? []; + } + + /** + * @return array The return value is always an array with zero or more elements. Each + * element is an array with two keys ['class' => string, 'condition' => mixed]. + */ + private static function getPsr18Candidates() + { + $candidates = self::$classes[Psr18Client::class]; + + // HTTPlug 2.0 clients implements PSR18Client too. + foreach (self::$classes[HttpClient::class] as $c) { + try { + if (is_subclass_of($c['class'], Psr18Client::class)) { + $candidates[] = $c; + } + } catch (\Throwable $e) { + trigger_error(sprintf('Got exception "%s (%s)" while checking if a PSR-18 Client is available', get_class($e), $e->getMessage()), E_USER_WARNING); + } + } + + return $candidates; + } + + public static function buzzInstantiate() + { + return new \Buzz\Client\FileGetContents(MessageFactoryDiscovery::find()); + } + + public static function symfonyPsr18Instantiate() + { + return new SymfonyPsr18(null, Psr17FactoryDiscovery::findResponseFactory(), Psr17FactoryDiscovery::findStreamFactory()); + } + + public static function isGuzzleImplementingPsr18() + { + return defined('GuzzleHttp\ClientInterface::MAJOR_VERSION'); + } + + /** + * Can be used as a condition. + * + * @return bool + */ + public static function isPsr17FactoryInstalled() + { + try { + Psr17FactoryDiscovery::findResponseFactory(); + } catch (NotFoundException $e) { + return false; + } catch (\Throwable $e) { + trigger_error(sprintf('Got exception "%s (%s)" while checking if a PSR-17 ResponseFactory is available', get_class($e), $e->getMessage()), E_USER_WARNING); + + return false; + } + + return true; + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Strategy/CommonPsr17ClassesStrategy.php b/www/multitube/vendor/php-http/discovery/src/Strategy/CommonPsr17ClassesStrategy.php new file mode 100644 index 0000000..fc26778 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Strategy/CommonPsr17ClassesStrategy.php @@ -0,0 +1,105 @@ + + */ +final class CommonPsr17ClassesStrategy implements DiscoveryStrategy +{ + /** + * @var array + */ + private static $classes = [ + RequestFactoryInterface::class => [ + 'Phalcon\Http\Message\RequestFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\RequestFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\RequestFactory', + 'Http\Factory\Guzzle\RequestFactory', + 'Http\Factory\Slim\RequestFactory', + 'Laminas\Diactoros\RequestFactory', + 'Slim\Psr7\Factory\RequestFactory', + ], + ResponseFactoryInterface::class => [ + 'Phalcon\Http\Message\ResponseFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\ResponseFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\ResponseFactory', + 'Http\Factory\Guzzle\ResponseFactory', + 'Http\Factory\Slim\ResponseFactory', + 'Laminas\Diactoros\ResponseFactory', + 'Slim\Psr7\Factory\ResponseFactory', + ], + ServerRequestFactoryInterface::class => [ + 'Phalcon\Http\Message\ServerRequestFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\ServerRequestFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\ServerRequestFactory', + 'Http\Factory\Guzzle\ServerRequestFactory', + 'Http\Factory\Slim\ServerRequestFactory', + 'Laminas\Diactoros\ServerRequestFactory', + 'Slim\Psr7\Factory\ServerRequestFactory', + ], + StreamFactoryInterface::class => [ + 'Phalcon\Http\Message\StreamFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\StreamFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\StreamFactory', + 'Http\Factory\Guzzle\StreamFactory', + 'Http\Factory\Slim\StreamFactory', + 'Laminas\Diactoros\StreamFactory', + 'Slim\Psr7\Factory\StreamFactory', + ], + UploadedFileFactoryInterface::class => [ + 'Phalcon\Http\Message\UploadedFileFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\UploadedFileFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\UploadedFileFactory', + 'Http\Factory\Guzzle\UploadedFileFactory', + 'Http\Factory\Slim\UploadedFileFactory', + 'Laminas\Diactoros\UploadedFileFactory', + 'Slim\Psr7\Factory\UploadedFileFactory', + ], + UriFactoryInterface::class => [ + 'Phalcon\Http\Message\UriFactory', + 'Nyholm\Psr7\Factory\Psr17Factory', + 'Zend\Diactoros\UriFactory', + 'GuzzleHttp\Psr7\HttpFactory', + 'Http\Factory\Diactoros\UriFactory', + 'Http\Factory\Guzzle\UriFactory', + 'Http\Factory\Slim\UriFactory', + 'Laminas\Diactoros\UriFactory', + 'Slim\Psr7\Factory\UriFactory', + ], + ]; + + /** + * {@inheritdoc} + */ + public static function getCandidates($type) + { + $candidates = []; + if (isset(self::$classes[$type])) { + foreach (self::$classes[$type] as $class) { + $candidates[] = ['class' => $class, 'condition' => [$class]]; + } + } + + return $candidates; + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Strategy/DiscoveryStrategy.php b/www/multitube/vendor/php-http/discovery/src/Strategy/DiscoveryStrategy.php new file mode 100644 index 0000000..641485a --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Strategy/DiscoveryStrategy.php @@ -0,0 +1,23 @@ + + */ +interface DiscoveryStrategy +{ + /** + * Find a resource of a specific type. + * + * @param string $type + * + * @return array The return value is always an array with zero or more elements. Each + * element is an array with two keys ['class' => string, 'condition' => mixed]. + * + * @throws StrategyUnavailableException if we cannot use this strategy. + */ + public static function getCandidates($type); +} diff --git a/www/multitube/vendor/php-http/discovery/src/Strategy/MockClientStrategy.php b/www/multitube/vendor/php-http/discovery/src/Strategy/MockClientStrategy.php new file mode 100644 index 0000000..0cee3f7 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Strategy/MockClientStrategy.php @@ -0,0 +1,27 @@ + + */ +final class MockClientStrategy implements DiscoveryStrategy +{ + /** + * {@inheritdoc} + */ + public static function getCandidates($type) + { + if (is_a(HttpClient::class, $type, true) || is_a(HttpAsyncClient::class, $type, true)) { + return [['class' => Mock::class, 'condition' => Mock::class]]; + } + + return []; + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/Strategy/PuliBetaStrategy.php b/www/multitube/vendor/php-http/discovery/src/Strategy/PuliBetaStrategy.php new file mode 100644 index 0000000..c1e1fb7 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/Strategy/PuliBetaStrategy.php @@ -0,0 +1,92 @@ + + * @author Márk Sági-Kazár + */ +class PuliBetaStrategy implements DiscoveryStrategy +{ + /** + * @var GeneratedPuliFactory + */ + protected static $puliFactory; + + /** + * @var Discovery + */ + protected static $puliDiscovery; + + /** + * @return GeneratedPuliFactory + * + * @throws PuliUnavailableException + */ + private static function getPuliFactory() + { + if (null === self::$puliFactory) { + if (!defined('PULI_FACTORY_CLASS')) { + throw new PuliUnavailableException('Puli Factory is not available'); + } + + $puliFactoryClass = PULI_FACTORY_CLASS; + + if (!ClassDiscovery::safeClassExists($puliFactoryClass)) { + throw new PuliUnavailableException('Puli Factory class does not exist'); + } + + self::$puliFactory = new $puliFactoryClass(); + } + + return self::$puliFactory; + } + + /** + * Returns the Puli discovery layer. + * + * @return Discovery + * + * @throws PuliUnavailableException + */ + private static function getPuliDiscovery() + { + if (!isset(self::$puliDiscovery)) { + $factory = self::getPuliFactory(); + $repository = $factory->createRepository(); + + self::$puliDiscovery = $factory->createDiscovery($repository); + } + + return self::$puliDiscovery; + } + + /** + * {@inheritdoc} + */ + public static function getCandidates($type) + { + $returnData = []; + $bindings = self::getPuliDiscovery()->findBindings($type); + + foreach ($bindings as $binding) { + $condition = true; + if ($binding->hasParameterValue('depends')) { + $condition = $binding->getParameterValue('depends'); + } + $returnData[] = ['class' => $binding->getClassName(), 'condition' => $condition]; + } + + return $returnData; + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/StreamFactoryDiscovery.php b/www/multitube/vendor/php-http/discovery/src/StreamFactoryDiscovery.php new file mode 100644 index 0000000..e11c49a --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/StreamFactoryDiscovery.php @@ -0,0 +1,34 @@ + + * + * @deprecated This will be removed in 2.0. Consider using Psr17FactoryDiscovery. + */ +final class StreamFactoryDiscovery extends ClassDiscovery +{ + /** + * Finds a Stream Factory. + * + * @return StreamFactory + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $streamFactory = static::findOneByType(StreamFactory::class); + } catch (DiscoveryFailedException $e) { + throw new NotFoundException('No stream factories found. To use Guzzle, Diactoros or Slim Framework factories install php-http/message and the chosen message implementation.', 0, $e); + } + + return static::instantiateClass($streamFactory); + } +} diff --git a/www/multitube/vendor/php-http/discovery/src/UriFactoryDiscovery.php b/www/multitube/vendor/php-http/discovery/src/UriFactoryDiscovery.php new file mode 100644 index 0000000..db3add2 --- /dev/null +++ b/www/multitube/vendor/php-http/discovery/src/UriFactoryDiscovery.php @@ -0,0 +1,34 @@ + + * + * @deprecated This will be removed in 2.0. Consider using Psr17FactoryDiscovery. + */ +final class UriFactoryDiscovery extends ClassDiscovery +{ + /** + * Finds a URI Factory. + * + * @return UriFactory + * + * @throws Exception\NotFoundException + */ + public static function find() + { + try { + $uriFactory = static::findOneByType(UriFactory::class); + } catch (DiscoveryFailedException $e) { + throw new NotFoundException('No uri factories found. To use Guzzle, Diactoros or Slim Framework factories install php-http/message and the chosen message implementation.', 0, $e); + } + + return static::instantiateClass($uriFactory); + } +} diff --git a/www/multitube/vendor/php-http/httplug/CHANGELOG.md b/www/multitube/vendor/php-http/httplug/CHANGELOG.md new file mode 100644 index 0000000..8478966 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/CHANGELOG.md @@ -0,0 +1,72 @@ +# Change Log + +## 1.1.0 - 2016-08-31 + +- Added HttpFulfilledPromise and HttpRejectedPromise which respect the HttpAsyncClient interface + +## 1.0.0 - 2016-01-26 + +### Removed + +- Stability configuration from composer + + +## 1.0.0-RC1 - 2016-01-12 + +### Changed + +- Updated package files +- Updated promise dependency to RC1 + + +## 1.0.0-beta - 2015-12-17 + +### Added + +- Puli configuration and binding types + +### Changed + +- Exception concept + + +## 1.0.0-alpha3 - 2015-12-13 + +### Changed + +- Async client does not throw exceptions + +### Removed + +- Promise interface moved to its own repository: [php-http/promise](https://github.com/php-http/promise) + + +## 1.0.0-alpha2 - 2015-11-16 + +### Added + +- Async client and Promise interface + + +## 1.0.0-alpha - 2015-10-26 + +### Added + +- Better domain exceptions. + +### Changed + +- Purpose of the library: general HTTP CLient abstraction. + +### Removed + +- Request options: they should be configured at construction time. +- Multiple request sending: should be done asynchronously using Async Client. +- `getName` method + + +## 0.1.0 - 2015-06-03 + +### Added + +- Initial release diff --git a/www/multitube/vendor/php-http/httplug/LICENSE b/www/multitube/vendor/php-http/httplug/LICENSE new file mode 100644 index 0000000..48741e4 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2014-2015 Eric GELOEN +Copyright (c) 2015-2016 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/httplug/README.md b/www/multitube/vendor/php-http/httplug/README.md new file mode 100644 index 0000000..f46212b --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/README.md @@ -0,0 +1,57 @@ +# HTTPlug + +[![Latest Version](https://img.shields.io/github/release/php-http/httplug.svg?style=flat-square)](https://github.com/php-http/httplug/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/travis/php-http/httplug.svg?style=flat-square)](https://travis-ci.org/php-http/httplug) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/httplug.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/httplug) +[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/httplug.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/httplug) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/httplug.svg?style=flat-square)](https://packagist.org/packages/php-http/httplug) + +[![Slack Status](http://slack.httplug.io/badge.svg)](http://slack.httplug.io) +[![Email](https://img.shields.io/badge/email-team@httplug.io-blue.svg?style=flat-square)](mailto:team@httplug.io) + +**HTTPlug, the HTTP client abstraction for PHP.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/httplug +``` + + +## Intro + +This is the contract package for HTTP Client. +Use it to create HTTP Clients which are interoperable and compatible with [PSR-7](http://www.php-fig.org/psr/psr-7/). + +This library is the official successor of the [ivory http adapter](https://github.com/egeloen/ivory-http-adapter). + + +## Documentation + +Please see the [official documentation](http://docs.php-http.org). + + +## Testing + +``` bash +$ composer test +``` + + +## Contributing + +Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html). + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/httplug/composer.json b/www/multitube/vendor/php-http/httplug/composer.json new file mode 100644 index 0000000..f74c4d3 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/composer.json @@ -0,0 +1,40 @@ +{ + "name": "php-http/httplug", + "description": "HTTPlug, the HTTP client abstraction for PHP", + "license": "MIT", + "keywords": ["http", "client"], + "homepage": "http://httplug.io", + "authors": [ + { + "name": "Eric GELOEN", + "email": "geloen.eric@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0", + "php-http/promise": "^1.0" + }, + "require-dev": { + "phpspec/phpspec": "^2.4", + "henrikbjorn/phpspec-code-coverage" : "^1.0" + }, + "autoload": { + "psr-4": { + "Http\\Client\\": "src/" + } + }, + "scripts": { + "test": "vendor/bin/phpspec run", + "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" + }, + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + } +} diff --git a/www/multitube/vendor/php-http/httplug/puli.json b/www/multitube/vendor/php-http/httplug/puli.json new file mode 100644 index 0000000..4168331 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/puli.json @@ -0,0 +1,12 @@ +{ + "version": "1.0", + "name": "php-http/httplug", + "binding-types": { + "Http\\Client\\HttpAsyncClient": { + "description": "Async HTTP Client" + }, + "Http\\Client\\HttpClient": { + "description": "HTTP Client" + } + } +} diff --git a/www/multitube/vendor/php-http/httplug/src/Exception.php b/www/multitube/vendor/php-http/httplug/src/Exception.php new file mode 100644 index 0000000..e7382c3 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Exception.php @@ -0,0 +1,12 @@ + + */ +interface Exception +{ +} diff --git a/www/multitube/vendor/php-http/httplug/src/Exception/HttpException.php b/www/multitube/vendor/php-http/httplug/src/Exception/HttpException.php new file mode 100644 index 0000000..f4f32a4 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Exception/HttpException.php @@ -0,0 +1,74 @@ + + */ +class HttpException extends RequestException +{ + /** + * @var ResponseInterface + */ + protected $response; + + /** + * @param string $message + * @param RequestInterface $request + * @param ResponseInterface $response + * @param \Exception|null $previous + */ + public function __construct( + $message, + RequestInterface $request, + ResponseInterface $response, + \Exception $previous = null + ) { + parent::__construct($message, $request, $previous); + + $this->response = $response; + $this->code = $response->getStatusCode(); + } + + /** + * Returns the response. + * + * @return ResponseInterface + */ + public function getResponse() + { + return $this->response; + } + + /** + * Factory method to create a new exception with a normalized error message. + * + * @param RequestInterface $request + * @param ResponseInterface $response + * @param \Exception|null $previous + * + * @return HttpException + */ + public static function create( + RequestInterface $request, + ResponseInterface $response, + \Exception $previous = null + ) { + $message = sprintf( + '[url] %s [http method] %s [status code] %s [reason phrase] %s', + $request->getRequestTarget(), + $request->getMethod(), + $response->getStatusCode(), + $response->getReasonPhrase() + ); + + return new self($message, $request, $response, $previous); + } +} diff --git a/www/multitube/vendor/php-http/httplug/src/Exception/NetworkException.php b/www/multitube/vendor/php-http/httplug/src/Exception/NetworkException.php new file mode 100644 index 0000000..f2198e5 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Exception/NetworkException.php @@ -0,0 +1,14 @@ + + */ +class NetworkException extends RequestException +{ +} diff --git a/www/multitube/vendor/php-http/httplug/src/Exception/RequestException.php b/www/multitube/vendor/php-http/httplug/src/Exception/RequestException.php new file mode 100644 index 0000000..cdce14b --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Exception/RequestException.php @@ -0,0 +1,43 @@ + + */ +class RequestException extends TransferException +{ + /** + * @var RequestInterface + */ + private $request; + + /** + * @param string $message + * @param RequestInterface $request + * @param \Exception|null $previous + */ + public function __construct($message, RequestInterface $request, \Exception $previous = null) + { + $this->request = $request; + + parent::__construct($message, 0, $previous); + } + + /** + * Returns the request. + * + * @return RequestInterface + */ + public function getRequest() + { + return $this->request; + } +} diff --git a/www/multitube/vendor/php-http/httplug/src/Exception/TransferException.php b/www/multitube/vendor/php-http/httplug/src/Exception/TransferException.php new file mode 100644 index 0000000..a858cf5 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Exception/TransferException.php @@ -0,0 +1,14 @@ + + */ +class TransferException extends \RuntimeException implements Exception +{ +} diff --git a/www/multitube/vendor/php-http/httplug/src/HttpAsyncClient.php b/www/multitube/vendor/php-http/httplug/src/HttpAsyncClient.php new file mode 100644 index 0000000..492e511 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/HttpAsyncClient.php @@ -0,0 +1,27 @@ + + */ +interface HttpAsyncClient +{ + /** + * Sends a PSR-7 request in an asynchronous way. + * + * Exceptions related to processing the request are available from the returned Promise. + * + * @param RequestInterface $request + * + * @return Promise Resolves a PSR-7 Response or fails with an Http\Client\Exception. + * + * @throws \Exception If processing the request is impossible (eg. bad configuration). + */ + public function sendAsyncRequest(RequestInterface $request); +} diff --git a/www/multitube/vendor/php-http/httplug/src/HttpClient.php b/www/multitube/vendor/php-http/httplug/src/HttpClient.php new file mode 100644 index 0000000..0e51749 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/HttpClient.php @@ -0,0 +1,28 @@ + + * @author Márk Sági-Kazár + * @author David Buchmann + */ +interface HttpClient +{ + /** + * Sends a PSR-7 request. + * + * @param RequestInterface $request + * + * @return ResponseInterface + * + * @throws \Http\Client\Exception If an error happens during processing the request. + * @throws \Exception If processing the request is impossible (eg. bad configuration). + */ + public function sendRequest(RequestInterface $request); +} diff --git a/www/multitube/vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php b/www/multitube/vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php new file mode 100644 index 0000000..6779e44 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Promise/HttpFulfilledPromise.php @@ -0,0 +1,57 @@ +response = $response; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onFulfilled) { + return $this; + } + + try { + return new self($onFulfilled($this->response)); + } catch (Exception $e) { + return new HttpRejectedPromise($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::FULFILLED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + return $this->response; + } + } +} diff --git a/www/multitube/vendor/php-http/httplug/src/Promise/HttpRejectedPromise.php b/www/multitube/vendor/php-http/httplug/src/Promise/HttpRejectedPromise.php new file mode 100644 index 0000000..bfb0738 --- /dev/null +++ b/www/multitube/vendor/php-http/httplug/src/Promise/HttpRejectedPromise.php @@ -0,0 +1,56 @@ +exception = $exception; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onRejected) { + return $this; + } + + try { + return new HttpFulfilledPromise($onRejected($this->exception)); + } catch (Exception $e) { + return new self($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::REJECTED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + throw $this->exception; + } + } +} diff --git a/www/multitube/vendor/php-http/message-factory/CHANGELOG.md b/www/multitube/vendor/php-http/message-factory/CHANGELOG.md new file mode 100644 index 0000000..4711924 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/CHANGELOG.md @@ -0,0 +1,65 @@ +# Change Log + + +## 1.0.2 - 2015-12-19 + +### Added + +- Request and Response factory binding types to Puli + + +## 1.0.1 - 2015-12-17 + +### Added + +- Puli configuration and binding types + + +## 1.0.0 - 2015-12-15 + +### Added + +- Response Factory in order to be reused in Message and Server Message factories +- Request Factory + +### Changed + +- Message Factory extends Request and Response factories + + +## 1.0.0-RC1 - 2015-12-14 + +### Added + +- CS check + +### Changed + +- RuntimeException is thrown when the StreamFactory cannot write to the underlying stream + + +## 0.3.0 - 2015-11-16 + +### Removed + +- Client Context Factory +- Factory Awares and Templates + + +## 0.2.0 - 2015-11-16 + +### Changed + +- Reordered the parameters when creating a message to have the protocol last, +as its the least likely to need to be changed. + + +## 0.1.0 - 2015-06-01 + +### Added + +- Initial release + +### Changed + +- Helpers are renamed to templates diff --git a/www/multitube/vendor/php-http/message-factory/LICENSE b/www/multitube/vendor/php-http/message-factory/LICENSE new file mode 100644 index 0000000..8e2c4a0 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/message-factory/README.md b/www/multitube/vendor/php-http/message-factory/README.md new file mode 100644 index 0000000..4654495 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/README.md @@ -0,0 +1,36 @@ +# PSR-7 Message Factory + +[![Latest Version](https://img.shields.io/github/release/php-http/message-factory.svg?style=flat-square)](https://github.com/php-http/message-factory/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/message-factory.svg?style=flat-square)](https://packagist.org/packages/php-http/message-factory) + +**Factory interfaces for PSR-7 HTTP Message.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/message-factory +``` + + +## Documentation + +Please see the [official documentation](http://php-http.readthedocs.org/en/latest/message-factory/). + + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details. + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/message-factory/composer.json b/www/multitube/vendor/php-http/message-factory/composer.json new file mode 100644 index 0000000..7c72feb --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/composer.json @@ -0,0 +1,27 @@ +{ + "name": "php-http/message-factory", + "description": "Factory interfaces for PSR-7 HTTP Message", + "license": "MIT", + "keywords": ["http", "factory", "message", "stream", "uri"], + "homepage": "http://php-http.org", + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": ">=5.4", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + } +} diff --git a/www/multitube/vendor/php-http/message-factory/puli.json b/www/multitube/vendor/php-http/message-factory/puli.json new file mode 100644 index 0000000..08d3762 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/puli.json @@ -0,0 +1,43 @@ +{ + "version": "1.0", + "binding-types": { + "Http\\Message\\MessageFactory": { + "description": "PSR-7 Message Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\RequestFactory": { + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\ResponseFactory": { + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\StreamFactory": { + "description": "PSR-7 Stream Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + }, + "Http\\Message\\UriFactory": { + "description": "PSR-7 URI Factory", + "parameters": { + "depends": { + "description": "Optional class dependency which can be checked by consumers" + } + } + } + } +} diff --git a/www/multitube/vendor/php-http/message-factory/src/MessageFactory.php b/www/multitube/vendor/php-http/message-factory/src/MessageFactory.php new file mode 100644 index 0000000..965aaa8 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/src/MessageFactory.php @@ -0,0 +1,12 @@ + + */ +interface MessageFactory extends RequestFactory, ResponseFactory +{ +} diff --git a/www/multitube/vendor/php-http/message-factory/src/RequestFactory.php b/www/multitube/vendor/php-http/message-factory/src/RequestFactory.php new file mode 100644 index 0000000..624e82f --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/src/RequestFactory.php @@ -0,0 +1,34 @@ + + */ +interface RequestFactory +{ + /** + * Creates a new PSR-7 request. + * + * @param string $method + * @param string|UriInterface $uri + * @param array $headers + * @param resource|string|StreamInterface|null $body + * @param string $protocolVersion + * + * @return RequestInterface + */ + public function createRequest( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ); +} diff --git a/www/multitube/vendor/php-http/message-factory/src/ResponseFactory.php b/www/multitube/vendor/php-http/message-factory/src/ResponseFactory.php new file mode 100644 index 0000000..2411ed3 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/src/ResponseFactory.php @@ -0,0 +1,35 @@ + + */ +interface ResponseFactory +{ + /** + * Creates a new PSR-7 response. + * + * @param int $statusCode + * @param string|null $reasonPhrase + * @param array $headers + * @param resource|string|StreamInterface|null $body + * @param string $protocolVersion + * + * @return ResponseInterface + */ + public function createResponse( + $statusCode = 200, + $reasonPhrase = null, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ); +} diff --git a/www/multitube/vendor/php-http/message-factory/src/StreamFactory.php b/www/multitube/vendor/php-http/message-factory/src/StreamFactory.php new file mode 100644 index 0000000..327a902 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/src/StreamFactory.php @@ -0,0 +1,25 @@ + + */ +interface StreamFactory +{ + /** + * Creates a new PSR-7 stream. + * + * @param string|resource|StreamInterface|null $body + * + * @return StreamInterface + * + * @throws \InvalidArgumentException If the stream body is invalid. + * @throws \RuntimeException If creating the stream from $body fails. + */ + public function createStream($body = null); +} diff --git a/www/multitube/vendor/php-http/message-factory/src/UriFactory.php b/www/multitube/vendor/php-http/message-factory/src/UriFactory.php new file mode 100644 index 0000000..f05e625 --- /dev/null +++ b/www/multitube/vendor/php-http/message-factory/src/UriFactory.php @@ -0,0 +1,24 @@ + + */ +interface UriFactory +{ + /** + * Creates an PSR-7 URI. + * + * @param string|UriInterface $uri + * + * @return UriInterface + * + * @throws \InvalidArgumentException If the $uri argument can not be converted into a valid URI. + */ + public function createUri($uri); +} diff --git a/www/multitube/vendor/php-http/message/CHANGELOG.md b/www/multitube/vendor/php-http/message/CHANGELOG.md new file mode 100644 index 0000000..b36da2d --- /dev/null +++ b/www/multitube/vendor/php-http/message/CHANGELOG.md @@ -0,0 +1,237 @@ +# Change Log + + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [1.11.0] - 2020-02-01 + +- Migrated from `zendframework/zend-diactoros` to `laminas/laminas-diactoros`. + Users are encouraged to update their dependencies by simply replacing the Zend package with the Laminas package. + Due to the [laminas-zendframework-brige](https://github.com/laminas/laminas-zendframework-bridge), BC changes + are not expected and legacy code does not need to be refactored (though it is + [recommended and simple](https://docs.laminas.dev/migration/)). +- The diactoros factories of `php-http/message` will return objects from the `Laminas\Diactoros\` namespace, if + the respective classes are available via autoloading, but continue to return objects from `Zend\Diactoros\` + namespace otherwise. + +- Allow to specify the hashing algorithm for WSSE authentication. + +## [1.10.0] - 2020-11-11 + +- Added support for PHP 8.0. + +## [1.9.1] - 2020-10-13 + +- Improved detection of binary stream to not consider newlines, carriage return or tabs as binary. + +## [1.9.0] - 2020-08-17 + +- Omitted binary body in FullHttpMessageFormatter and CurlCommandFormatter. + `[binary stream omitted]` will be shown instead. + +### Added + +- New Header authentication method for arbitrary header authentication. + +## [1.8.0] - 2019-08-05 + +### Changed + +- Raised minimum PHP version to 7.1 + +### Fixed + +- Fatal error on `CurlCommandFormatter` when body is larger than `escapeshellarg` allowed length. +- Do not read stream in message formatter if stream is not seekable. + +## [1.7.2] - 2018-10-30 + +### Fixed + +- FilteredStream uses `@trigger_error` instead of throwing exceptions to not + break careless users. You still need to fix your stream code to respect + `isSeekable`. Seeking does not work as expected, and we will add exceptions + in version 2. + +## [1.7.1] - 2018-10-29 + +### Fixed + +- FilteredStream is not actually seekable + + +## [1.7.0] - 2018-08-15 + +### Fixed + +- Fix CurlCommandFormatter for binary request payloads +- Fix QueryParam authentication to assemble proper URL regardless of PHP `arg_separator.output` directive +- Do not pass `null` parameters to `Clue\StreamFilter\fun` + +### Changed + +- Dropped tests on HHVM + + +## [1.6.0] - 2017-07-05 + +### Added + +- CookieUtil::parseDate to create a date from cookie date string + +### Fixed + +- Fix curl command of CurlFormatter when there is an user-agent header + + +## [1.5.0] - 2017-02-14 + +### Added + +- Check for empty string in Stream factories +- Cookie::createWithoutValidation Static constructor to create a cookie. Will not perform any attribute validation during instantiation. +- Cookie::isValid Method to check if cookie attributes are valid. + +### Fixed + +- FilteredStream::getSize returns null because the contents size is unknown. +- Stream factories does not rewinds streams. The previous behavior was not coherent between factories and inputs. + +### Deprecated + +- FilteredStream::getReadFilter The read filter is internal and should never be used by consuming code. +- FilteredStream::getWriteFilter We did not implement writing to the streams at all. And if we do, the filter is an internal information and should not be used by consuming code. + + +## [1.4.1] - 2016-12-16 + +### Fixed + +- Cookie::matchPath Cookie with root path (`/`) will not match sub path (e.g. `/cookie`). + + +## [1.4.0] - 2016-10-20 + +### Added + +- Message, stream and URI factories for [Slim Framework](https://github.com/slimphp/Slim) +- BufferedStream that allow you to decorate a non-seekable stream with a seekable one. +- cUrlFormatter to be able to redo the request with a cURL command + + +## [1.3.1] - 2016-07-15 + +### Fixed + +- FullHttpMessageFormatter will not read from streams that you cannot rewind (non-seekable) +- FullHttpMessageFormatter will not read from the stream if $maxBodyLength is zero +- FullHttpMessageFormatter rewinds streams after they are read + + +## [1.3.0] - 2016-07-14 + +### Added + +- FullHttpMessageFormatter to include headers and body in the formatted message + +### Fixed + +- #41: Response builder broke header value + + +## [1.2.0] - 2016-03-29 + +### Added + +- The RequestMatcher is built after the Symfony RequestMatcher and separates + scheme, host and path expressions and provides an option to filter on the + method +- New RequestConditional authentication method using request matchers +- Add automatic basic auth info detection based on the URL + +### Changed + +- Improved ResponseBuilder + +### Deprecated + +- RegexRequestMatcher, use RequestMatcher instead +- Matching authenitcation method, use RequestConditional instead + + +## [1.1.0] - 2016-02-25 + +### Added + + - Add a request matcher interface and regex implementation + - Add a callback request matcher implementation + - Add a ResponseBuilder, to create PSR7 Response from a string + +### Fixed + + - Fix casting string on a FilteredStream not filtering the output + + +## [1.0.0] - 2016-01-27 + + +## [0.2.0] - 2015-12-29 + +### Added + +- Autoregistration of stream filters using Composer autoload +- Cookie +- [Apigen](http://www.apigen.org/) configuration + + +## [0.1.2] - 2015-12-26 + +### Added + +- Request and response factory bindings + +### Fixed + +- Chunk filter namespace in Dechunk stream + + +## [0.1.1] - 2015-12-25 + +### Added + +- Formatter + + +## 0.1.0 - 2015-12-24 + +### Added + +- Authentication +- Encoding +- Message decorator +- Message factory (Guzzle, Diactoros) + + +[Unreleased]: https://github.com/php-http/message/compare/1.10.0...HEAD +[1.10.0]: https://github.com/php-http/message/compare/1.9.1...1.10.0 +[1.9.1]: https://github.com/php-http/message/compare/1.9.0...1.9.1 +[1.9.0]: https://github.com/php-http/message/compare/1.8.0...1.9.0 +[1.8.0]: https://github.com/php-http/message/compare/1.7.2...1.8.0 +[1.7.2]: https://github.com/php-http/message/compare/v1.7.1...1.7.2 +[1.7.1]: https://github.com/php-http/message/compare/1.7.0...v1.7.1 +[1.7.0]: https://github.com/php-http/message/compare/1.6.0...1.7.0 +[1.6.0]: https://github.com/php-http/message/compare/1.5.0...1.6.0 +[1.5.0]: https://github.com/php-http/message/compare/v1.4.1...1.5.0 +[1.4.1]: https://github.com/php-http/message/compare/v1.4.0...v1.4.1 +[1.4.0]: https://github.com/php-http/message/compare/v1.3.1...v1.4.0 +[1.3.1]: https://github.com/php-http/message/compare/v1.3.0...v1.3.1 +[1.3.0]: https://github.com/php-http/message/compare/v1.2.0...v1.3.0 +[1.2.0]: https://github.com/php-http/message/compare/v1.1.0...v1.2.0 +[1.1.0]: https://github.com/php-http/message/compare/v1.0.0...v1.1.0 +[1.0.0]: https://github.com/php-http/message/compare/0.2.0...v1.0.0 +[0.2.0]: https://github.com/php-http/message/compare/v0.1.2...0.2.0 +[0.1.2]: https://github.com/php-http/message/compare/v0.1.1...v0.1.2 +[0.1.1]: https://github.com/php-http/message/compare/v0.1.0...v0.1.1 diff --git a/www/multitube/vendor/php-http/message/LICENSE b/www/multitube/vendor/php-http/message/LICENSE new file mode 100644 index 0000000..4558d6f --- /dev/null +++ b/www/multitube/vendor/php-http/message/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2016 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/message/README.md b/www/multitube/vendor/php-http/message/README.md new file mode 100644 index 0000000..df1a7d5 --- /dev/null +++ b/www/multitube/vendor/php-http/message/README.md @@ -0,0 +1,51 @@ +# HTTP Message + +[![Latest Version](https://img.shields.io/github/release/php-http/message.svg?style=flat-square)](https://github.com/php-http/message/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/php-http/message/CI?style=flat-square)](https://github.com/php-http/message/actions?query=workflow%3ACI+branch%3Amaster) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/message.svg?style=flat-square)](https://packagist.org/packages/php-http/message) + +**HTTP Message related tools.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/message +``` + + +## Intro + +This package contains various PSR-7 tools which might be useful in an HTTP workflow: + +- Authentication method implementations +- Various Stream encoding tools +- Message decorators +- Message factory implementations for Guzzle PSR-7 and Diactoros +- Cookie implementation +- Request matchers + + +## Documentation + +Please see the [official documentation](http://docs.php-http.org/en/latest/message.html). + + +## Testing + +``` bash +$ composer test +``` + + +## Credits + +Thanks to [Cuzzle](https://github.com/namshi/cuzzle) for inpiration for the `CurlCommandFormatter`. + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/message/apigen.neon b/www/multitube/vendor/php-http/message/apigen.neon new file mode 100644 index 0000000..0ba1a18 --- /dev/null +++ b/www/multitube/vendor/php-http/message/apigen.neon @@ -0,0 +1,6 @@ +source: + - src/ + +destination: build/api/ + +templateTheme: bootstrap diff --git a/www/multitube/vendor/php-http/message/composer.json b/www/multitube/vendor/php-http/message/composer.json new file mode 100644 index 0000000..fc67cd0 --- /dev/null +++ b/www/multitube/vendor/php-http/message/composer.json @@ -0,0 +1,65 @@ +{ + "name": "php-http/message", + "description": "HTTP Message related tools", + "keywords": [ + "message", + "http", + "psr-7" + ], + "homepage": "http://php-http.org", + "license": "MIT", + "authors": [ + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php": "^7.1 || ^8.0", + "clue/stream-filter": "^1.5", + "php-http/message-factory": "^1.0.2", + "psr/http-message": "^1.0" + }, + "provide": { + "php-http/message-factory-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "ergebnis/composer-normalize": "^2.6", + "guzzlehttp/psr7": "^1.0", + "phpspec/phpspec": "^5.1 || ^6.3", + "slim/slim": "^3.0", + "laminas/laminas-diactoros": "^2.0" + }, + "suggest": { + "ext-zlib": "Used with compressor/decompressor streams", + "guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories", + "laminas/laminas-diactoros": "Used with Diactoros Factories", + "slim/slim": "Used with Slim Framework PSR-7 implementation" + }, + "config": { + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Http\\Message\\": "src/" + }, + "files": [ + "src/filters.php" + ] + }, + "autoload-dev": { + "psr-4": { + "spec\\Http\\Message\\": "spec/" + } + }, + "scripts": { + "test": "vendor/bin/phpspec run", + "test-ci": "vendor/bin/phpspec run -c phpspec.ci.yml" + } +} diff --git a/www/multitube/vendor/php-http/message/puli.json b/www/multitube/vendor/php-http/message/puli.json new file mode 100644 index 0000000..024a85d --- /dev/null +++ b/www/multitube/vendor/php-http/message/puli.json @@ -0,0 +1,111 @@ +{ + "version": "1.0", + "name": "php-http/message", + "bindings": { + "064d003d-78a1-48c4-8f3b-1f92ff25da69": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", + "type": "Http\\Message\\MessageFactory", + "parameters": { + "depends": "Zend\\Diactoros\\Request" + } + }, + "0836751e-6558-4d1b-8993-4a52012947c3": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", + "type": "Http\\Message\\ResponseFactory" + }, + "1d127622-dc61-4bfa-b9da-d221548d72c3": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", + "type": "Http\\Message\\RequestFactory" + }, + "2438c2d0-0658-441f-8855-ddaf0f87d54d": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", + "type": "Http\\Message\\MessageFactory", + "parameters": { + "depends": "GuzzleHttp\\Psr7\\Request" + } + }, + "253aa08c-d705-46e7-b1d2-e28c97eef792": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", + "type": "Http\\Message\\RequestFactory", + "parameters": { + "depends": "GuzzleHttp\\Psr7\\Request" + } + }, + "273a34f9-62f4-4ba1-9801-b1284d49ff89": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\StreamFactory\\GuzzleStreamFactory", + "type": "Http\\Message\\StreamFactory", + "parameters": { + "depends": "GuzzleHttp\\Psr7\\Stream" + } + }, + "304b83db-b594-4d83-ae75-1f633adf92f7": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\UriFactory\\GuzzleUriFactory", + "type": "Http\\Message\\UriFactory", + "parameters": { + "depends": "GuzzleHttp\\Psr7\\Uri" + } + }, + "3f4bc1cd-aa95-4702-9fa7-65408e471691": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\UriFactory\\DiactorosUriFactory", + "type": "Http\\Message\\UriFactory", + "parameters": { + "depends": "Zend\\Diactoros\\Uri" + } + }, + "4672a6ee-ad9e-4109-a5d1-b7d46f26c7a1": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\SlimMessageFactory", + "type": "Http\\Message\\MessageFactory" + }, + "6234e947-d3bd-43eb-97d5-7f9e22e6bb1b": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", + "type": "Http\\Message\\ResponseFactory", + "parameters": { + "depends": "Zend\\Diactoros\\Response" + } + }, + "6a9ad6ce-d82c-470f-8e30-60f21d9d95bf": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\UriFactory\\SlimUriFactory", + "type": "Http\\Message\\UriFactory" + }, + "72c2afa0-ea56-4d03-adb6-a9f241a8a734": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\StreamFactory\\SlimStreamFactory", + "type": "Http\\Message\\StreamFactory" + }, + "95c1be8f-39fe-4abd-8351-92cb14379a75": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\StreamFactory\\DiactorosStreamFactory", + "type": "Http\\Message\\StreamFactory", + "parameters": { + "depends": "Zend\\Diactoros\\Stream" + } + }, + "a018af27-7590-4dcf-83a1-497f95604cd6": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\GuzzleMessageFactory", + "type": "Http\\Message\\ResponseFactory", + "parameters": { + "depends": "GuzzleHttp\\Psr7\\Response" + } + }, + "c07955b1-de46-43db-923b-d07fae9382cb": { + "_class": "Puli\\Discovery\\Binding\\ClassBinding", + "class": "Http\\Message\\MessageFactory\\DiactorosMessageFactory", + "type": "Http\\Message\\RequestFactory", + "parameters": { + "depends": "Zend\\Diactoros\\Request" + } + } + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication.php b/www/multitube/vendor/php-http/message/src/Authentication.php new file mode 100644 index 0000000..0fe0cb3 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication.php @@ -0,0 +1,25 @@ + + */ +interface Authentication +{ + /** + * Alter the request to add the authentication credentials. + * + * To do that, the implementation might use pre-stored credentials or do + * separate HTTP requests to obtain a valid token. + * + * @param RequestInterface $request The request without authentication information + * + * @return RequestInterface The request with added authentication information + */ + public function authenticate(RequestInterface $request); +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/AutoBasicAuth.php b/www/multitube/vendor/php-http/message/src/Authentication/AutoBasicAuth.php new file mode 100644 index 0000000..7b6a429 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/AutoBasicAuth.php @@ -0,0 +1,48 @@ + + */ +final class AutoBasicAuth implements Authentication +{ + /** + * Whether user info should be removed from the URI. + * + * @var bool + */ + private $shouldRemoveUserInfo; + + /** + * @param bool|true $shouldRremoveUserInfo + */ + public function __construct($shouldRremoveUserInfo = true) + { + $this->shouldRemoveUserInfo = (bool) $shouldRremoveUserInfo; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + $uri = $request->getUri(); + $userInfo = $uri->getUserInfo(); + + if (!empty($userInfo)) { + if ($this->shouldRemoveUserInfo) { + $request = $request->withUri($uri->withUserInfo('')); + } + + $request = $request->withHeader('Authorization', sprintf('Basic %s', base64_encode($userInfo))); + } + + return $request; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/BasicAuth.php b/www/multitube/vendor/php-http/message/src/Authentication/BasicAuth.php new file mode 100644 index 0000000..23618a5 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/BasicAuth.php @@ -0,0 +1,44 @@ + + */ +final class BasicAuth implements Authentication +{ + /** + * @var string + */ + private $username; + + /** + * @var string + */ + private $password; + + /** + * @param string $username + * @param string $password + */ + public function __construct($username, $password) + { + $this->username = $username; + $this->password = $password; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + $header = sprintf('Basic %s', base64_encode(sprintf('%s:%s', $this->username, $this->password))); + + return $request->withHeader('Authorization', $header); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/Bearer.php b/www/multitube/vendor/php-http/message/src/Authentication/Bearer.php new file mode 100644 index 0000000..a8fb21a --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/Bearer.php @@ -0,0 +1,37 @@ + + */ +final class Bearer implements Authentication +{ + /** + * @var string + */ + private $token; + + /** + * @param string $token + */ + public function __construct($token) + { + $this->token = $token; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + $header = sprintf('Bearer %s', $this->token); + + return $request->withHeader('Authorization', $header); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/Chain.php b/www/multitube/vendor/php-http/message/src/Authentication/Chain.php new file mode 100644 index 0000000..71002bb --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/Chain.php @@ -0,0 +1,47 @@ + + */ +final class Chain implements Authentication +{ + /** + * @var Authentication[] + */ + private $authenticationChain = []; + + /** + * @param Authentication[] $authenticationChain + */ + public function __construct(array $authenticationChain = []) + { + foreach ($authenticationChain as $authentication) { + if (!$authentication instanceof Authentication) { + throw new \InvalidArgumentException( + 'Members of the authentication chain must be of type Http\Message\Authentication' + ); + } + } + + $this->authenticationChain = $authenticationChain; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + foreach ($this->authenticationChain as $authentication) { + $request = $authentication->authenticate($request); + } + + return $request; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/Header.php b/www/multitube/vendor/php-http/message/src/Authentication/Header.php new file mode 100644 index 0000000..97a04dd --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/Header.php @@ -0,0 +1,33 @@ +name = $name; + $this->value = $value; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + return $request->withHeader($this->name, $this->value); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/Matching.php b/www/multitube/vendor/php-http/message/src/Authentication/Matching.php new file mode 100644 index 0000000..7a5c247 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/Matching.php @@ -0,0 +1,69 @@ + + * + * @deprecated since since version 1.2, and will be removed in 2.0. Use {@link RequestConditional} instead. + */ +final class Matching implements Authentication +{ + /** + * @var Authentication + */ + private $authentication; + + /** + * @var CallbackRequestMatcher + */ + private $matcher; + + public function __construct(Authentication $authentication, callable $matcher = null) + { + if (is_null($matcher)) { + $matcher = function () { + return true; + }; + } + + $this->authentication = $authentication; + $this->matcher = new CallbackRequestMatcher($matcher); + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + if ($this->matcher->matches($request)) { + return $this->authentication->authenticate($request); + } + + return $request; + } + + /** + * Creates a matching authentication for an URL. + * + * @param string $url + * + * @return self + */ + public static function createUrlMatcher(Authentication $authentication, $url) + { + $matcher = function (RequestInterface $request) use ($url) { + return preg_match($url, $request->getRequestTarget()); + }; + + return new static($authentication, $matcher); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/QueryParam.php b/www/multitube/vendor/php-http/message/src/Authentication/QueryParam.php new file mode 100644 index 0000000..7f95d44 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/QueryParam.php @@ -0,0 +1,47 @@ + + */ +final class QueryParam implements Authentication +{ + /** + * @var array + */ + private $params = []; + + public function __construct(array $params) + { + $this->params = $params; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + $uri = $request->getUri(); + $query = $uri->getQuery(); + $params = []; + + parse_str($query, $params); + + $params = array_merge($params, $this->params); + + $query = http_build_query($params, null, '&'); + + $uri = $uri->withQuery($query); + + return $request->withUri($uri); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/RequestConditional.php b/www/multitube/vendor/php-http/message/src/Authentication/RequestConditional.php new file mode 100644 index 0000000..01062cf --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/RequestConditional.php @@ -0,0 +1,43 @@ + + */ +final class RequestConditional implements Authentication +{ + /** + * @var RequestMatcher + */ + private $requestMatcher; + + /** + * @var Authentication + */ + private $authentication; + + public function __construct(RequestMatcher $requestMatcher, Authentication $authentication) + { + $this->requestMatcher = $requestMatcher; + $this->authentication = $authentication; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + if ($this->requestMatcher->matches($request)) { + return $this->authentication->authenticate($request); + } + + return $request; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Authentication/Wsse.php b/www/multitube/vendor/php-http/message/src/Authentication/Wsse.php new file mode 100644 index 0000000..f343633 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Authentication/Wsse.php @@ -0,0 +1,68 @@ + + */ +final class Wsse implements Authentication +{ + /** + * @var string + */ + private $username; + + /** + * @var string + */ + private $password; + + /** + * @var string + */ + private $hashAlgorithm; + + /** + * @param string $username + * @param string $password + * @param string $hashAlgorithm To use a better hashing algorithm than the weak sha1, pass the algorithm to use, e.g. "sha512" + */ + public function __construct($username, $password, $hashAlgorithm = 'sha1') + { + $this->username = $username; + $this->password = $password; + if (false === in_array($hashAlgorithm, hash_algos())) { + throw new InvalidArgumentException(sprintf('Unaccepted hashing algorithm: %s', $hashAlgorithm)); + } + $this->hashAlgorithm = $hashAlgorithm; + } + + /** + * {@inheritdoc} + */ + public function authenticate(RequestInterface $request) + { + $nonce = substr(md5(uniqid(uniqid().'_', true)), 0, 16); + $created = date('c'); + $digest = base64_encode(hash($this->hashAlgorithm, base64_decode($nonce).$created.$this->password, true)); + + $wsse = sprintf( + 'UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"', + $this->username, + $digest, + $nonce, + $created + ); + + return $request + ->withHeader('Authorization', 'WSSE profile="UsernameToken"') + ->withHeader('X-WSSE', $wsse) + ; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Builder/ResponseBuilder.php b/www/multitube/vendor/php-http/message/src/Builder/ResponseBuilder.php new file mode 100644 index 0000000..4c3ecfc --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Builder/ResponseBuilder.php @@ -0,0 +1,146 @@ +response = $response; + } + + /** + * Return response. + * + * @return ResponseInterface + */ + public function getResponse() + { + return $this->response; + } + + /** + * Add headers represented by an array of header lines. + * + * @param string[] $headers response headers as array of header lines + * + * @return $this + * + * @throws \UnexpectedValueException for invalid header values + * @throws \InvalidArgumentException for invalid status code arguments + */ + public function setHeadersFromArray(array $headers) + { + $status = array_shift($headers); + $this->setStatus($status); + + foreach ($headers as $headerLine) { + $headerLine = trim($headerLine); + if ('' === $headerLine) { + continue; + } + + $this->addHeader($headerLine); + } + + return $this; + } + + /** + * Add headers represented by a single string. + * + * @param string $headers response headers as single string + * + * @return $this + * + * @throws \InvalidArgumentException if $headers is not a string on object with __toString() + * @throws \UnexpectedValueException for invalid header values + */ + public function setHeadersFromString($headers) + { + if (!(is_string($headers) + || (is_object($headers) && method_exists($headers, '__toString'))) + ) { + throw new \InvalidArgumentException( + sprintf( + '%s expects parameter 1 to be a string, %s given', + __METHOD__, + is_object($headers) ? get_class($headers) : gettype($headers) + ) + ); + } + + $this->setHeadersFromArray(explode("\r\n", $headers)); + + return $this; + } + + /** + * Set response status from a status string. + * + * @param string $statusLine response status as a string + * + * @return $this + * + * @throws \InvalidArgumentException for invalid status line + */ + public function setStatus($statusLine) + { + $parts = explode(' ', $statusLine, 3); + if (count($parts) < 2 || 0 !== strpos(strtolower($parts[0]), 'http/')) { + throw new \InvalidArgumentException( + sprintf('"%s" is not a valid HTTP status line', $statusLine) + ); + } + + $reasonPhrase = count($parts) > 2 ? $parts[2] : ''; + $this->response = $this->response + ->withStatus((int) $parts[1], $reasonPhrase) + ->withProtocolVersion(substr($parts[0], 5)); + + return $this; + } + + /** + * Add header represented by a string. + * + * @param string $headerLine response header as a string + * + * @return $this + * + * @throws \InvalidArgumentException for invalid header names or values + */ + public function addHeader($headerLine) + { + $parts = explode(':', $headerLine, 2); + if (2 !== count($parts)) { + throw new \InvalidArgumentException( + sprintf('"%s" is not a valid HTTP header line', $headerLine) + ); + } + $name = trim($parts[0]); + $value = trim($parts[1]); + if ($this->response->hasHeader($name)) { + $this->response = $this->response->withAddedHeader($name, $value); + } else { + $this->response = $this->response->withHeader($name, $value); + } + + return $this; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Cookie.php b/www/multitube/vendor/php-http/message/src/Cookie.php new file mode 100644 index 0000000..0cc2d43 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Cookie.php @@ -0,0 +1,524 @@ + + * + * @see http://tools.ietf.org/search/rfc6265 + */ +final class Cookie +{ + /** + * @var string + */ + private $name; + + /** + * @var string|null + */ + private $value; + + /** + * @var int|null + */ + private $maxAge; + + /** + * @var string|null + */ + private $domain; + + /** + * @var string + */ + private $path; + + /** + * @var bool + */ + private $secure; + + /** + * @var bool + */ + private $httpOnly; + + /** + * Expires attribute is HTTP 1.0 only and should be avoided. + * + * @var \DateTime|null + */ + private $expires; + + /** + * @param string $name + * @param string|null $value + * @param int|null $maxAge + * @param string|null $domain + * @param string|null $path + * @param bool $secure + * @param bool $httpOnly + * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided. + * + * @throws \InvalidArgumentException if name, value or max age is not valid + */ + public function __construct( + $name, + $value = null, + $maxAge = null, + $domain = null, + $path = null, + $secure = false, + $httpOnly = false, + \DateTime $expires = null + ) { + $this->validateName($name); + $this->validateValue($value); + $this->validateMaxAge($maxAge); + + $this->name = $name; + $this->value = $value; + $this->maxAge = $maxAge; + $this->expires = $expires; + $this->domain = $this->normalizeDomain($domain); + $this->path = $this->normalizePath($path); + $this->secure = (bool) $secure; + $this->httpOnly = (bool) $httpOnly; + } + + /** + * Creates a new cookie without any attribute validation. + * + * @param string $name + * @param string|null $value + * @param int $maxAge + * @param string|null $domain + * @param string|null $path + * @param bool $secure + * @param bool $httpOnly + * @param \DateTime|null $expires Expires attribute is HTTP 1.0 only and should be avoided. + */ + public static function createWithoutValidation( + $name, + $value = null, + $maxAge = null, + $domain = null, + $path = null, + $secure = false, + $httpOnly = false, + \DateTime $expires = null + ) { + $cookie = new self('name', null, null, $domain, $path, $secure, $httpOnly, $expires); + $cookie->name = $name; + $cookie->value = $value; + $cookie->maxAge = $maxAge; + + return $cookie; + } + + /** + * Returns the name. + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Returns the value. + * + * @return string|null + */ + public function getValue() + { + return $this->value; + } + + /** + * Checks if there is a value. + * + * @return bool + */ + public function hasValue() + { + return isset($this->value); + } + + /** + * Sets the value. + * + * @param string|null $value + * + * @return Cookie + */ + public function withValue($value) + { + $this->validateValue($value); + + $new = clone $this; + $new->value = $value; + + return $new; + } + + /** + * Returns the max age. + * + * @return int|null + */ + public function getMaxAge() + { + return $this->maxAge; + } + + /** + * Checks if there is a max age. + * + * @return bool + */ + public function hasMaxAge() + { + return isset($this->maxAge); + } + + /** + * Sets the max age. + * + * @param int|null $maxAge + * + * @return Cookie + */ + public function withMaxAge($maxAge) + { + $this->validateMaxAge($maxAge); + + $new = clone $this; + $new->maxAge = $maxAge; + + return $new; + } + + /** + * Returns the expiration time. + * + * @return \DateTime|null + */ + public function getExpires() + { + return $this->expires; + } + + /** + * Checks if there is an expiration time. + * + * @return bool + */ + public function hasExpires() + { + return isset($this->expires); + } + + /** + * Sets the expires. + * + * @return Cookie + */ + public function withExpires(\DateTime $expires = null) + { + $new = clone $this; + $new->expires = $expires; + + return $new; + } + + /** + * Checks if the cookie is expired. + * + * @return bool + */ + public function isExpired() + { + return isset($this->expires) and $this->expires < new \DateTime(); + } + + /** + * Returns the domain. + * + * @return string|null + */ + public function getDomain() + { + return $this->domain; + } + + /** + * Checks if there is a domain. + * + * @return bool + */ + public function hasDomain() + { + return isset($this->domain); + } + + /** + * Sets the domain. + * + * @param string|null $domain + * + * @return Cookie + */ + public function withDomain($domain) + { + $new = clone $this; + $new->domain = $this->normalizeDomain($domain); + + return $new; + } + + /** + * Checks whether this cookie is meant for this domain. + * + * @see http://tools.ietf.org/html/rfc6265#section-5.1.3 + * + * @param string $domain + * + * @return bool + */ + public function matchDomain($domain) + { + // Domain is not set or exact match + if (!$this->hasDomain() || 0 === strcasecmp($domain, $this->domain)) { + return true; + } + + // Domain is not an IP address + if (filter_var($domain, FILTER_VALIDATE_IP)) { + return false; + } + + return (bool) preg_match(sprintf('/\b%s$/i', preg_quote($this->domain)), $domain); + } + + /** + * Returns the path. + * + * @return string + */ + public function getPath() + { + return $this->path; + } + + /** + * Sets the path. + * + * @param string|null $path + * + * @return Cookie + */ + public function withPath($path) + { + $new = clone $this; + $new->path = $this->normalizePath($path); + + return $new; + } + + /** + * Checks whether this cookie is meant for this path. + * + * @see http://tools.ietf.org/html/rfc6265#section-5.1.4 + * + * @param string $path + * + * @return bool + */ + public function matchPath($path) + { + return $this->path === $path || (0 === strpos($path, rtrim($this->path, '/').'/')); + } + + /** + * Checks whether this cookie may only be sent over HTTPS. + * + * @return bool + */ + public function isSecure() + { + return $this->secure; + } + + /** + * Sets whether this cookie should only be sent over HTTPS. + * + * @param bool $secure + * + * @return Cookie + */ + public function withSecure($secure) + { + $new = clone $this; + $new->secure = (bool) $secure; + + return $new; + } + + /** + * Check whether this cookie may not be accessed through Javascript. + * + * @return bool + */ + public function isHttpOnly() + { + return $this->httpOnly; + } + + /** + * Sets whether this cookie may not be accessed through Javascript. + * + * @param bool $httpOnly + * + * @return Cookie + */ + public function withHttpOnly($httpOnly) + { + $new = clone $this; + $new->httpOnly = (bool) $httpOnly; + + return $new; + } + + /** + * Checks if this cookie represents the same cookie as $cookie. + * + * This does not compare the values, only name, domain and path. + * + * @param Cookie $cookie + * + * @return bool + */ + public function match(self $cookie) + { + return $this->name === $cookie->name && $this->domain === $cookie->domain and $this->path === $cookie->path; + } + + /** + * Validates cookie attributes. + * + * @return bool + */ + public function isValid() + { + try { + $this->validateName($this->name); + $this->validateValue($this->value); + $this->validateMaxAge($this->maxAge); + } catch (\InvalidArgumentException $e) { + return false; + } + + return true; + } + + /** + * Validates the name attribute. + * + * @see http://tools.ietf.org/search/rfc2616#section-2.2 + * + * @param string $name + * + * @throws \InvalidArgumentException if the name is empty or contains invalid characters + */ + private function validateName($name) + { + if (strlen($name) < 1) { + throw new \InvalidArgumentException('The name cannot be empty'); + } + + // Name attribute is a token as per spec in RFC 2616 + if (preg_match('/[\x00-\x20\x22\x28-\x29\x2C\x2F\x3A-\x40\x5B-\x5D\x7B\x7D\x7F]/', $name)) { + throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); + } + } + + /** + * Validates a value. + * + * @see http://tools.ietf.org/html/rfc6265#section-4.1.1 + * + * @param string|null $value + * + * @throws \InvalidArgumentException if the value contains invalid characters + */ + private function validateValue($value) + { + if (isset($value)) { + if (preg_match('/[^\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/', $value)) { + throw new \InvalidArgumentException(sprintf('The cookie value "%s" contains invalid characters.', $value)); + } + } + } + + /** + * Validates a Max-Age attribute. + * + * @param int|null $maxAge + * + * @throws \InvalidArgumentException if the Max-Age is not an empty or integer value + */ + private function validateMaxAge($maxAge) + { + if (isset($maxAge)) { + if (!is_int($maxAge)) { + throw new \InvalidArgumentException('Max-Age must be integer'); + } + } + } + + /** + * Remove the leading '.' and lowercase the domain as per spec in RFC 6265. + * + * @see http://tools.ietf.org/html/rfc6265#section-4.1.2.3 + * @see http://tools.ietf.org/html/rfc6265#section-5.1.3 + * @see http://tools.ietf.org/html/rfc6265#section-5.2.3 + * + * @param string|null $domain + * + * @return string + */ + private function normalizeDomain($domain) + { + if (isset($domain)) { + $domain = ltrim(strtolower($domain), '.'); + } + + return $domain; + } + + /** + * Processes path as per spec in RFC 6265. + * + * @see http://tools.ietf.org/html/rfc6265#section-5.1.4 + * @see http://tools.ietf.org/html/rfc6265#section-5.2.4 + * + * @param string|null $path + * + * @return string + */ + private function normalizePath($path) + { + $path = rtrim($path, '/'); + + if (empty($path) or '/' !== substr($path, 0, 1)) { + $path = '/'; + } + + return $path; + } +} diff --git a/www/multitube/vendor/php-http/message/src/CookieJar.php b/www/multitube/vendor/php-http/message/src/CookieJar.php new file mode 100644 index 0000000..1479cc6 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/CookieJar.php @@ -0,0 +1,210 @@ + + */ +final class CookieJar implements \Countable, \IteratorAggregate +{ + /** + * @var \SplObjectStorage + */ + private $cookies; + + public function __construct() + { + $this->cookies = new \SplObjectStorage(); + } + + /** + * Checks if there is a cookie. + * + * @return bool + */ + public function hasCookie(Cookie $cookie) + { + return $this->cookies->contains($cookie); + } + + /** + * Adds a cookie. + */ + public function addCookie(Cookie $cookie) + { + if (!$this->hasCookie($cookie)) { + $cookies = $this->getMatchingCookies($cookie); + + foreach ($cookies as $matchingCookie) { + if ($cookie->getValue() !== $matchingCookie->getValue() || $cookie->getMaxAge() > $matchingCookie->getMaxAge()) { + $this->removeCookie($matchingCookie); + + continue; + } + } + + if ($cookie->hasValue()) { + $this->cookies->attach($cookie); + } + } + } + + /** + * Removes a cookie. + */ + public function removeCookie(Cookie $cookie) + { + $this->cookies->detach($cookie); + } + + /** + * Returns the cookies. + * + * @return Cookie[] + */ + public function getCookies() + { + $match = function ($matchCookie) { + return true; + }; + + return $this->findMatchingCookies($match); + } + + /** + * Returns all matching cookies. + * + * @return Cookie[] + */ + public function getMatchingCookies(Cookie $cookie) + { + $match = function ($matchCookie) use ($cookie) { + return $matchCookie->match($cookie); + }; + + return $this->findMatchingCookies($match); + } + + /** + * Finds matching cookies based on a callable. + * + * @return Cookie[] + */ + private function findMatchingCookies(callable $match) + { + $cookies = []; + + foreach ($this->cookies as $cookie) { + if ($match($cookie)) { + $cookies[] = $cookie; + } + } + + return $cookies; + } + + /** + * Checks if there are cookies. + * + * @return bool + */ + public function hasCookies() + { + return $this->cookies->count() > 0; + } + + /** + * Sets the cookies and removes any previous one. + * + * @param Cookie[] $cookies + */ + public function setCookies(array $cookies) + { + $this->clear(); + $this->addCookies($cookies); + } + + /** + * Adds some cookies. + * + * @param Cookie[] $cookies + */ + public function addCookies(array $cookies) + { + foreach ($cookies as $cookie) { + $this->addCookie($cookie); + } + } + + /** + * Removes some cookies. + * + * @param Cookie[] $cookies + */ + public function removeCookies(array $cookies) + { + foreach ($cookies as $cookie) { + $this->removeCookie($cookie); + } + } + + /** + * Removes cookies which match the given parameters. + * + * Null means that parameter should not be matched + * + * @param string|null $name + * @param string|null $domain + * @param string|null $path + */ + public function removeMatchingCookies($name = null, $domain = null, $path = null) + { + $match = function ($cookie) use ($name, $domain, $path) { + $match = true; + + if (isset($name)) { + $match = $match && ($cookie->getName() === $name); + } + + if (isset($domain)) { + $match = $match && $cookie->matchDomain($domain); + } + + if (isset($path)) { + $match = $match && $cookie->matchPath($path); + } + + return $match; + }; + + $cookies = $this->findMatchingCookies($match); + + $this->removeCookies($cookies); + } + + /** + * Removes all cookies. + */ + public function clear() + { + $this->cookies = new \SplObjectStorage(); + } + + /** + * {@inheritdoc} + */ + public function count() + { + return $this->cookies->count(); + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return clone $this->cookies; + } +} diff --git a/www/multitube/vendor/php-http/message/src/CookieUtil.php b/www/multitube/vendor/php-http/message/src/CookieUtil.php new file mode 100644 index 0000000..44c5314 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/CookieUtil.php @@ -0,0 +1,53 @@ + + */ +trait MessageDecorator +{ + /** + * @var MessageInterface + */ + private $message; + + /** + * Returns the decorated message. + * + * Since the underlying Message is immutable as well + * exposing it is not an issue, because it's state cannot be altered + * + * @return MessageInterface + */ + public function getMessage() + { + return $this->message; + } + + /** + * {@inheritdoc} + */ + public function getProtocolVersion() + { + return $this->message->getProtocolVersion(); + } + + /** + * {@inheritdoc} + */ + public function withProtocolVersion($version) + { + $new = clone $this; + $new->message = $this->message->withProtocolVersion($version); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getHeaders() + { + return $this->message->getHeaders(); + } + + /** + * {@inheritdoc} + */ + public function hasHeader($header) + { + return $this->message->hasHeader($header); + } + + /** + * {@inheritdoc} + */ + public function getHeader($header) + { + return $this->message->getHeader($header); + } + + /** + * {@inheritdoc} + */ + public function getHeaderLine($header) + { + return $this->message->getHeaderLine($header); + } + + /** + * {@inheritdoc} + */ + public function withHeader($header, $value) + { + $new = clone $this; + $new->message = $this->message->withHeader($header, $value); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function withAddedHeader($header, $value) + { + $new = clone $this; + $new->message = $this->message->withAddedHeader($header, $value); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function withoutHeader($header) + { + $new = clone $this; + $new->message = $this->message->withoutHeader($header); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getBody() + { + return $this->message->getBody(); + } + + /** + * {@inheritdoc} + */ + public function withBody(StreamInterface $body) + { + $new = clone $this; + $new->message = $this->message->withBody($body); + + return $new; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Decorator/RequestDecorator.php b/www/multitube/vendor/php-http/message/src/Decorator/RequestDecorator.php new file mode 100644 index 0000000..bd254a8 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Decorator/RequestDecorator.php @@ -0,0 +1,86 @@ + + */ +trait RequestDecorator +{ + use MessageDecorator { + getMessage as getRequest; + } + + /** + * Exchanges the underlying request with another. + * + * @return self + */ + public function withRequest(RequestInterface $request) + { + $new = clone $this; + $new->message = $request; + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getRequestTarget() + { + return $this->message->getRequestTarget(); + } + + /** + * {@inheritdoc} + */ + public function withRequestTarget($requestTarget) + { + $new = clone $this; + $new->message = $this->message->withRequestTarget($requestTarget); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getMethod() + { + return $this->message->getMethod(); + } + + /** + * {@inheritdoc} + */ + public function withMethod($method) + { + $new = clone $this; + $new->message = $this->message->withMethod($method); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getUri() + { + return $this->message->getUri(); + } + + /** + * {@inheritdoc} + */ + public function withUri(UriInterface $uri, $preserveHost = false) + { + $new = clone $this; + $new->message = $this->message->withUri($uri, $preserveHost); + + return $new; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Decorator/ResponseDecorator.php b/www/multitube/vendor/php-http/message/src/Decorator/ResponseDecorator.php new file mode 100644 index 0000000..20319ed --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Decorator/ResponseDecorator.php @@ -0,0 +1,55 @@ + + */ +trait ResponseDecorator +{ + use MessageDecorator { + getMessage as getResponse; + } + + /** + * Exchanges the underlying response with another. + * + * @return self + */ + public function withResponse(ResponseInterface $response) + { + $new = clone $this; + $new->message = $response; + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getStatusCode() + { + return $this->message->getStatusCode(); + } + + /** + * {@inheritdoc} + */ + public function withStatus($code, $reasonPhrase = '') + { + $new = clone $this; + $new->message = $this->message->withStatus($code, $reasonPhrase); + + return $new; + } + + /** + * {@inheritdoc} + */ + public function getReasonPhrase() + { + return $this->message->getReasonPhrase(); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Decorator/StreamDecorator.php b/www/multitube/vendor/php-http/message/src/Decorator/StreamDecorator.php new file mode 100644 index 0000000..f405c7a --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Decorator/StreamDecorator.php @@ -0,0 +1,138 @@ + + */ +trait StreamDecorator +{ + /** + * @var StreamInterface + */ + protected $stream; + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->stream->__toString(); + } + + /** + * {@inheritdoc} + */ + public function close() + { + $this->stream->close(); + } + + /** + * {@inheritdoc} + */ + public function detach() + { + return $this->stream->detach(); + } + + /** + * {@inheritdoc} + */ + public function getSize() + { + return $this->stream->getSize(); + } + + /** + * {@inheritdoc} + */ + public function tell() + { + return $this->stream->tell(); + } + + /** + * {@inheritdoc} + */ + public function eof() + { + return $this->stream->eof(); + } + + /** + * {@inheritdoc} + */ + public function isSeekable() + { + return $this->stream->isSeekable(); + } + + /** + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET) + { + $this->stream->seek($offset, $whence); + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + $this->stream->rewind(); + } + + /** + * {@inheritdoc} + */ + public function isWritable() + { + return $this->stream->isWritable(); + } + + /** + * {@inheritdoc} + */ + public function write($string) + { + return $this->stream->write($string); + } + + /** + * {@inheritdoc} + */ + public function isReadable() + { + return $this->stream->isReadable(); + } + + /** + * {@inheritdoc} + */ + public function read($length) + { + return $this->stream->read($length); + } + + /** + * {@inheritdoc} + */ + public function getContents() + { + return $this->stream->getContents(); + } + + /** + * {@inheritdoc} + */ + public function getMetadata($key = null) + { + return $this->stream->getMetadata($key); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/ChunkStream.php b/www/multitube/vendor/php-http/message/src/Encoding/ChunkStream.php new file mode 100644 index 0000000..74c2fbd --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/ChunkStream.php @@ -0,0 +1,39 @@ + + */ +class ChunkStream extends FilteredStream +{ + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'chunk'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'dechunk'; + } + + /** + * {@inheritdoc} + */ + protected function fill() + { + parent::fill(); + + if ($this->stream->eof()) { + $this->buffer .= "0\r\n\r\n"; + } + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/CompressStream.php b/www/multitube/vendor/php-http/message/src/Encoding/CompressStream.php new file mode 100644 index 0000000..bdb740a --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/CompressStream.php @@ -0,0 +1,45 @@ + + */ +class CompressStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + if (!extension_loaded('zlib')) { + throw new \RuntimeException('The zlib extension must be enabled to use this stream'); + } + + parent::__construct($stream, ['window' => 15, 'level' => $level]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 15]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.deflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.inflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/DechunkStream.php b/www/multitube/vendor/php-http/message/src/Encoding/DechunkStream.php new file mode 100644 index 0000000..4cade83 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/DechunkStream.php @@ -0,0 +1,29 @@ + + */ +class DechunkStream extends FilteredStream +{ + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'dechunk'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'chunk'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/DecompressStream.php b/www/multitube/vendor/php-http/message/src/Encoding/DecompressStream.php new file mode 100644 index 0000000..ab3a345 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/DecompressStream.php @@ -0,0 +1,45 @@ + + */ +class DecompressStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + if (!extension_loaded('zlib')) { + throw new \RuntimeException('The zlib extension must be enabled to use this stream'); + } + + parent::__construct($stream, ['window' => 15]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 15, 'level' => $level]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.inflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.deflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/DeflateStream.php b/www/multitube/vendor/php-http/message/src/Encoding/DeflateStream.php new file mode 100644 index 0000000..2ab3e00 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/DeflateStream.php @@ -0,0 +1,41 @@ + + */ +class DeflateStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + parent::__construct($stream, ['window' => -15, 'level' => $level]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => -15]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.deflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.inflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/Filter/Chunk.php b/www/multitube/vendor/php-http/message/src/Encoding/Filter/Chunk.php new file mode 100644 index 0000000..0f8f53b --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/Filter/Chunk.php @@ -0,0 +1,30 @@ + + */ +class Chunk extends \php_user_filter +{ + /** + * {@inheritdoc} + */ + public function filter($in, $out, &$consumed, $closing) + { + while ($bucket = stream_bucket_make_writeable($in)) { + $lenbucket = stream_bucket_new($this->stream, dechex($bucket->datalen)."\r\n"); + stream_bucket_append($out, $lenbucket); + + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + + $lenbucket = stream_bucket_new($this->stream, "\r\n"); + stream_bucket_append($out, $lenbucket); + } + + return PSFS_PASS_ON; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/FilteredStream.php b/www/multitube/vendor/php-http/message/src/Encoding/FilteredStream.php new file mode 100644 index 0000000..a937c82 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/FilteredStream.php @@ -0,0 +1,234 @@ + + */ +abstract class FilteredStream implements StreamInterface +{ + use StreamDecorator { + rewind as private doRewind; + seek as private doSeek; + } + const BUFFER_SIZE = 8192; + + /** + * @var callable + */ + protected $readFilterCallback; + + /** + * @var resource + * + * @deprecated since version 1.5, will be removed in 2.0 + */ + protected $readFilter; + + /** + * @var callable + * + * @deprecated since version 1.5, will be removed in 2.0 + */ + protected $writeFilterCallback; + + /** + * @var resource + * + * @deprecated since version 1.5, will be removed in 2.0 + */ + protected $writeFilter; + + /** + * Internal buffer. + * + * @var string + */ + protected $buffer = ''; + + /** + * @param mixed|null $readFilterOptions + * @param mixed|null $writeFilterOptions deprecated since 1.5, will be removed in 2.0 + */ + public function __construct(StreamInterface $stream, $readFilterOptions = null, $writeFilterOptions = null) + { + if (null !== $readFilterOptions) { + $this->readFilterCallback = Filter\fun($this->readFilter(), $readFilterOptions); + } else { + $this->readFilterCallback = Filter\fun($this->readFilter()); + } + + if (null !== $writeFilterOptions) { + $this->writeFilterCallback = Filter\fun($this->writeFilter(), $writeFilterOptions); + + @trigger_error('The $writeFilterOptions argument is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); + } else { + $this->writeFilterCallback = Filter\fun($this->writeFilter()); + } + + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function read($length) + { + if (strlen($this->buffer) >= $length) { + $read = substr($this->buffer, 0, $length); + $this->buffer = substr($this->buffer, $length); + + return $read; + } + + if ($this->stream->eof()) { + $buffer = $this->buffer; + $this->buffer = ''; + + return $buffer; + } + + $read = $this->buffer; + $this->buffer = ''; + $this->fill(); + + return $read.$this->read($length - strlen($read)); + } + + /** + * {@inheritdoc} + */ + public function eof() + { + return $this->stream->eof() && '' === $this->buffer; + } + + /** + * Buffer is filled by reading underlying stream. + * + * Callback is reading once more even if the stream is ended. + * This allow to get last data in the PHP buffer otherwise this + * bug is present : https://bugs.php.net/bug.php?id=48725 + */ + protected function fill() + { + $readFilterCallback = $this->readFilterCallback; + $this->buffer .= $readFilterCallback($this->stream->read(self::BUFFER_SIZE)); + + if ($this->stream->eof()) { + $this->buffer .= $readFilterCallback(); + } + } + + /** + * {@inheritdoc} + */ + public function getContents() + { + $buffer = ''; + + while (!$this->eof()) { + $buf = $this->read(self::BUFFER_SIZE); + // Using a loose equality here to match on '' and false. + if (null == $buf) { + break; + } + + $buffer .= $buf; + } + + return $buffer; + } + + /** + * Always returns null because we can't tell the size of a stream when we filter. + */ + public function getSize() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->getContents(); + } + + /** + * Filtered streams are not seekable. + * + * We would need to buffer and process everything to allow seeking. + */ + public function isSeekable() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + @trigger_error('Filtered streams are not seekable. This method will start raising an exception in the next major version', E_USER_DEPRECATED); + $this->doRewind(); + } + + /** + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET) + { + @trigger_error('Filtered streams are not seekable. This method will start raising an exception in the next major version', E_USER_DEPRECATED); + $this->doSeek($offset, $whence); + } + + /** + * Returns the read filter name. + * + * @return string + * + * @deprecated since version 1.5, will be removed in 2.0 + */ + public function getReadFilter() + { + @trigger_error('The '.__CLASS__.'::'.__METHOD__.' method is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); + + return $this->readFilter(); + } + + /** + * Returns the write filter name. + * + * @return string + */ + abstract protected function readFilter(); + + /** + * Returns the write filter name. + * + * @return string + * + * @deprecated since version 1.5, will be removed in 2.0 + */ + public function getWriteFilter() + { + @trigger_error('The '.__CLASS__.'::'.__METHOD__.' method is deprecated since version 1.5 and will be removed in 2.0.', E_USER_DEPRECATED); + + return $this->writeFilter(); + } + + /** + * Returns the write filter name. + * + * @return string + */ + abstract protected function writeFilter(); +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/GzipDecodeStream.php b/www/multitube/vendor/php-http/message/src/Encoding/GzipDecodeStream.php new file mode 100644 index 0000000..92b5dad --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/GzipDecodeStream.php @@ -0,0 +1,45 @@ + + */ +class GzipDecodeStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + if (!extension_loaded('zlib')) { + throw new \RuntimeException('The zlib extension must be enabled to use this stream'); + } + + parent::__construct($stream, ['window' => 31]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 31, 'level' => $level]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.inflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.deflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/GzipEncodeStream.php b/www/multitube/vendor/php-http/message/src/Encoding/GzipEncodeStream.php new file mode 100644 index 0000000..13f097a --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/GzipEncodeStream.php @@ -0,0 +1,45 @@ + + */ +class GzipEncodeStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + if (!extension_loaded('zlib')) { + throw new \RuntimeException('The zlib extension must be enabled to use this stream'); + } + + parent::__construct($stream, ['window' => 31, 'level' => $level]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => 31]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.deflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.inflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Encoding/InflateStream.php b/www/multitube/vendor/php-http/message/src/Encoding/InflateStream.php new file mode 100644 index 0000000..06c5187 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Encoding/InflateStream.php @@ -0,0 +1,45 @@ + + */ +class InflateStream extends FilteredStream +{ + /** + * @param int $level + */ + public function __construct(StreamInterface $stream, $level = -1) + { + if (!extension_loaded('zlib')) { + throw new \RuntimeException('The zlib extension must be enabled to use this stream'); + } + + parent::__construct($stream, ['window' => -15]); + + // @deprecated will be removed in 2.0 + $this->writeFilterCallback = Filter\fun($this->writeFilter(), ['window' => -15, 'level' => $level]); + } + + /** + * {@inheritdoc} + */ + protected function readFilter() + { + return 'zlib.inflate'; + } + + /** + * {@inheritdoc} + */ + protected function writeFilter() + { + return 'zlib.deflate'; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Exception.php b/www/multitube/vendor/php-http/message/src/Exception.php new file mode 100644 index 0000000..80d4cd9 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Exception.php @@ -0,0 +1,10 @@ + + */ +interface Formatter +{ + /** + * Formats a request. + * + * @return string + */ + public function formatRequest(RequestInterface $request); + + /** + * Formats a response. + * + * @return string + */ + public function formatResponse(ResponseInterface $response); +} diff --git a/www/multitube/vendor/php-http/message/src/Formatter/CurlCommandFormatter.php b/www/multitube/vendor/php-http/message/src/Formatter/CurlCommandFormatter.php new file mode 100644 index 0000000..78b1d55 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Formatter/CurlCommandFormatter.php @@ -0,0 +1,93 @@ + + */ +class CurlCommandFormatter implements Formatter +{ + /** + * {@inheritdoc} + */ + public function formatRequest(RequestInterface $request) + { + $command = sprintf('curl %s', escapeshellarg((string) $request->getUri()->withFragment(''))); + if ('1.0' === $request->getProtocolVersion()) { + $command .= ' --http1.0'; + } elseif ('2.0' === $request->getProtocolVersion()) { + $command .= ' --http2'; + } + + $method = strtoupper($request->getMethod()); + if ('HEAD' === $method) { + $command .= ' --head'; + } elseif ('GET' !== $method) { + $command .= ' --request '.$method; + } + + $command .= $this->getHeadersAsCommandOptions($request); + + $body = $request->getBody(); + if ($body->getSize() > 0) { + // escapeshellarg argument max length on Windows, but longer body in curl command would be impractical anyways + if ($body->getSize() > 8192) { + $data = '[too long stream omitted]'; + } elseif ($body->isSeekable()) { + $data = $body->__toString(); + $body->rewind(); + // all non-printable ASCII characters and except for \t, \r, \n + if (preg_match('/([\x00-\x09\x0C\x0E-\x1F\x7F])/', $data)) { + $data = '[binary stream omitted]'; + } + } else { + $data = '[non-seekable stream omitted]'; + } + $escapedData = @escapeshellarg($data); + if (empty($escapedData)) { + $escapedData = 'We couldn\'t not escape the data properly'; + } + + $command .= sprintf(' --data %s', $escapedData); + } + + return $command; + } + + /** + * {@inheritdoc} + */ + public function formatResponse(ResponseInterface $response) + { + return ''; + } + + /** + * @return string + */ + private function getHeadersAsCommandOptions(RequestInterface $request) + { + $command = ''; + foreach ($request->getHeaders() as $name => $values) { + if ('host' === strtolower($name) && $values[0] === $request->getUri()->getHost()) { + continue; + } + + if ('user-agent' === strtolower($name)) { + $command .= sprintf(' -A %s', escapeshellarg($values[0])); + + continue; + } + + $command .= sprintf(' -H %s', escapeshellarg($name.': '.$request->getHeaderLine($name))); + } + + return $command; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Formatter/FullHttpMessageFormatter.php b/www/multitube/vendor/php-http/message/src/Formatter/FullHttpMessageFormatter.php new file mode 100644 index 0000000..64ce3ce --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Formatter/FullHttpMessageFormatter.php @@ -0,0 +1,100 @@ + + */ +class FullHttpMessageFormatter implements Formatter +{ + /** + * The maximum length of the body. + * + * @var int|null + */ + private $maxBodyLength; + + /** + * @param int|null $maxBodyLength + */ + public function __construct($maxBodyLength = 1000) + { + $this->maxBodyLength = $maxBodyLength; + } + + /** + * {@inheritdoc} + */ + public function formatRequest(RequestInterface $request) + { + $message = sprintf( + "%s %s HTTP/%s\n", + $request->getMethod(), + $request->getRequestTarget(), + $request->getProtocolVersion() + ); + + foreach ($request->getHeaders() as $name => $values) { + $message .= $name.': '.implode(', ', $values)."\n"; + } + + return $this->addBody($request, $message); + } + + /** + * {@inheritdoc} + */ + public function formatResponse(ResponseInterface $response) + { + $message = sprintf( + "HTTP/%s %s %s\n", + $response->getProtocolVersion(), + $response->getStatusCode(), + $response->getReasonPhrase() + ); + + foreach ($response->getHeaders() as $name => $values) { + $message .= $name.': '.implode(', ', $values)."\n"; + } + + return $this->addBody($response, $message); + } + + /** + * Add the message body if the stream is seekable. + * + * @param string $message + * + * @return string + */ + private function addBody(MessageInterface $request, $message) + { + $message .= "\n"; + $stream = $request->getBody(); + if (!$stream->isSeekable() || 0 === $this->maxBodyLength) { + // Do not read the stream + return $message; + } + + $data = $stream->__toString(); + $stream->rewind(); + + // all non-printable ASCII characters and except for \t, \r, \n + if (preg_match('/([\x00-\x09\x0C\x0E-\x1F\x7F])/', $data)) { + return $message.'[binary stream omitted]'; + } + + if (null === $this->maxBodyLength) { + return $message.$data; + } + + return $message.mb_substr($data, 0, $this->maxBodyLength); + } +} diff --git a/www/multitube/vendor/php-http/message/src/Formatter/SimpleFormatter.php b/www/multitube/vendor/php-http/message/src/Formatter/SimpleFormatter.php new file mode 100644 index 0000000..b1fcabd --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Formatter/SimpleFormatter.php @@ -0,0 +1,42 @@ + + * @author Márk Sági-Kazár + */ +class SimpleFormatter implements Formatter +{ + /** + * {@inheritdoc} + */ + public function formatRequest(RequestInterface $request) + { + return sprintf( + '%s %s %s', + $request->getMethod(), + $request->getUri()->__toString(), + $request->getProtocolVersion() + ); + } + + /** + * {@inheritdoc} + */ + public function formatResponse(ResponseInterface $response) + { + return sprintf( + '%s %s %s', + $response->getStatusCode(), + $response->getReasonPhrase(), + $response->getProtocolVersion() + ); + } +} diff --git a/www/multitube/vendor/php-http/message/src/MessageFactory/DiactorosMessageFactory.php b/www/multitube/vendor/php-http/message/src/MessageFactory/DiactorosMessageFactory.php new file mode 100644 index 0000000..6d54d35 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/MessageFactory/DiactorosMessageFactory.php @@ -0,0 +1,82 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory + */ +final class DiactorosMessageFactory implements MessageFactory +{ + /** + * @var DiactorosStreamFactory + */ + private $streamFactory; + + public function __construct() + { + $this->streamFactory = new DiactorosStreamFactory(); + } + + /** + * {@inheritdoc} + */ + public function createRequest( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + if (class_exists(LaminasRequest::class)) { + return (new LaminasRequest( + $uri, + $method, + $this->streamFactory->createStream($body), + $headers + ))->withProtocolVersion($protocolVersion); + } + + return (new ZendRequest( + $uri, + $method, + $this->streamFactory->createStream($body), + $headers + ))->withProtocolVersion($protocolVersion); + } + + /** + * {@inheritdoc} + */ + public function createResponse( + $statusCode = 200, + $reasonPhrase = null, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + if (class_exists(LaminasResponse::class)) { + return (new LaminasResponse( + $this->streamFactory->createStream($body), + $statusCode, + $headers + ))->withProtocolVersion($protocolVersion); + } + + return (new ZendResponse( + $this->streamFactory->createStream($body), + $statusCode, + $headers + ))->withProtocolVersion($protocolVersion); + } +} diff --git a/www/multitube/vendor/php-http/message/src/MessageFactory/GuzzleMessageFactory.php b/www/multitube/vendor/php-http/message/src/MessageFactory/GuzzleMessageFactory.php new file mode 100644 index 0000000..02989d9 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/MessageFactory/GuzzleMessageFactory.php @@ -0,0 +1,55 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory + */ +final class GuzzleMessageFactory implements MessageFactory +{ + /** + * {@inheritdoc} + */ + public function createRequest( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + return new Request( + $method, + $uri, + $headers, + $body, + $protocolVersion + ); + } + + /** + * {@inheritdoc} + */ + public function createResponse( + $statusCode = 200, + $reasonPhrase = null, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + return new Response( + $statusCode, + $headers, + $body, + $protocolVersion, + $reasonPhrase + ); + } +} diff --git a/www/multitube/vendor/php-http/message/src/MessageFactory/SlimMessageFactory.php b/www/multitube/vendor/php-http/message/src/MessageFactory/SlimMessageFactory.php new file mode 100644 index 0000000..bee9322 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/MessageFactory/SlimMessageFactory.php @@ -0,0 +1,74 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory + */ +final class SlimMessageFactory implements MessageFactory +{ + /** + * @var SlimStreamFactory + */ + private $streamFactory; + + /** + * @var SlimUriFactory + */ + private $uriFactory; + + public function __construct() + { + $this->streamFactory = new SlimStreamFactory(); + $this->uriFactory = new SlimUriFactory(); + } + + /** + * {@inheritdoc} + */ + public function createRequest( + $method, + $uri, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + return (new Request( + $method, + $this->uriFactory->createUri($uri), + new Headers($headers), + [], + [], + $this->streamFactory->createStream($body), + [] + ))->withProtocolVersion($protocolVersion); + } + + /** + * {@inheritdoc} + */ + public function createResponse( + $statusCode = 200, + $reasonPhrase = null, + array $headers = [], + $body = null, + $protocolVersion = '1.1' + ) { + return (new Response( + $statusCode, + new Headers($headers), + $this->streamFactory->createStream($body) + ))->withProtocolVersion($protocolVersion); + } +} diff --git a/www/multitube/vendor/php-http/message/src/RequestMatcher.php b/www/multitube/vendor/php-http/message/src/RequestMatcher.php new file mode 100644 index 0000000..94fe532 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/RequestMatcher.php @@ -0,0 +1,26 @@ + + */ +interface RequestMatcher +{ + /** + * Decides whether the rule(s) implemented by the strategy matches the supplied request. + * + * @param RequestInterface $request The PSR7 request to check for a match + * + * @return bool true if the request matches, false otherwise + */ + public function matches(RequestInterface $request); +} diff --git a/www/multitube/vendor/php-http/message/src/RequestMatcher/CallbackRequestMatcher.php b/www/multitube/vendor/php-http/message/src/RequestMatcher/CallbackRequestMatcher.php new file mode 100644 index 0000000..1197dd9 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/RequestMatcher/CallbackRequestMatcher.php @@ -0,0 +1,32 @@ + + */ +final class CallbackRequestMatcher implements RequestMatcher +{ + /** + * @var callable + */ + private $callback; + + public function __construct(callable $callback) + { + $this->callback = $callback; + } + + /** + * {@inheritdoc} + */ + public function matches(RequestInterface $request) + { + return (bool) call_user_func($this->callback, $request); + } +} diff --git a/www/multitube/vendor/php-http/message/src/RequestMatcher/RegexRequestMatcher.php b/www/multitube/vendor/php-http/message/src/RequestMatcher/RegexRequestMatcher.php new file mode 100644 index 0000000..91f3729 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/RequestMatcher/RegexRequestMatcher.php @@ -0,0 +1,41 @@ + + * + * @deprecated since version 1.2 and will be removed in 2.0. Use {@link RequestMatcher} instead. + */ +final class RegexRequestMatcher implements RequestMatcher +{ + /** + * Matching regex. + * + * @var string + */ + private $regex; + + /** + * @param string $regex + */ + public function __construct($regex) + { + $this->regex = $regex; + } + + /** + * {@inheritdoc} + */ + public function matches(RequestInterface $request) + { + return (bool) preg_match($this->regex, (string) $request->getUri()); + } +} diff --git a/www/multitube/vendor/php-http/message/src/RequestMatcher/RequestMatcher.php b/www/multitube/vendor/php-http/message/src/RequestMatcher/RequestMatcher.php new file mode 100644 index 0000000..e2aa021 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/RequestMatcher/RequestMatcher.php @@ -0,0 +1,78 @@ + + * @author Joel Wurtz + */ +final class RequestMatcher implements RequestMatcherInterface +{ + /** + * @var string + */ + private $path; + + /** + * @var string + */ + private $host; + + /** + * @var array + */ + private $methods = []; + + /** + * @var string[] + */ + private $schemes = []; + + /** + * The regular expressions used for path or host must be specified without delimiter. + * You do not need to escape the forward slash / to match it. + * + * @param string|null $path Regular expression for the path + * @param string|null $host Regular expression for the hostname + * @param string|string[]|null $methods Method or list of methods to match + * @param string|string[]|null $schemes Scheme or list of schemes to match (e.g. http or https) + */ + public function __construct($path = null, $host = null, $methods = [], $schemes = []) + { + $this->path = $path; + $this->host = $host; + $this->methods = array_map('strtoupper', (array) $methods); + $this->schemes = array_map('strtolower', (array) $schemes); + } + + /** + * {@inheritdoc} + * + * @api + */ + public function matches(RequestInterface $request) + { + if ($this->schemes && !in_array($request->getUri()->getScheme(), $this->schemes)) { + return false; + } + + if ($this->methods && !in_array($request->getMethod(), $this->methods)) { + return false; + } + + if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getUri()->getPath()))) { + return false; + } + + if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getUri()->getHost())) { + return false; + } + + return true; + } +} diff --git a/www/multitube/vendor/php-http/message/src/Stream/BufferedStream.php b/www/multitube/vendor/php-http/message/src/Stream/BufferedStream.php new file mode 100644 index 0000000..1eac974 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/Stream/BufferedStream.php @@ -0,0 +1,270 @@ +stream = $stream; + $this->size = $stream->getSize(); + + if ($useFileBuffer) { + $this->resource = fopen('php://temp/maxmemory:'.$memoryBuffer, 'rw+'); + } else { + $this->resource = fopen('php://memory', 'rw+'); + } + + if (false === $this->resource) { + throw new \RuntimeException('Cannot create a resource over temp or memory implementation'); + } + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + try { + $this->rewind(); + + return $this->getContents(); + } catch (\Throwable $throwable) { + return ''; + } catch (\Exception $exception) { // Layer to be BC with PHP 5, remove this when we only support PHP 7+ + return ''; + } + } + + /** + * {@inheritdoc} + */ + public function close() + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot close on a detached stream'); + } + + $this->stream->close(); + fclose($this->resource); + } + + /** + * {@inheritdoc} + */ + public function detach() + { + if (null === $this->resource) { + return; + } + + // Force reading the remaining data of the stream + $this->getContents(); + + $resource = $this->resource; + $this->stream->close(); + $this->stream = null; + $this->resource = null; + + return $resource; + } + + /** + * {@inheritdoc} + */ + public function getSize() + { + if (null === $this->resource) { + return; + } + + if (null === $this->size && $this->stream->eof()) { + return $this->written; + } + + return $this->size; + } + + /** + * {@inheritdoc} + */ + public function tell() + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot tell on a detached stream'); + } + + return ftell($this->resource); + } + + /** + * {@inheritdoc} + */ + public function eof() + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot call eof on a detached stream'); + } + + // We are at the end only when both our resource and underlying stream are at eof + return $this->stream->eof() && (ftell($this->resource) === $this->written); + } + + /** + * {@inheritdoc} + */ + public function isSeekable() + { + return null !== $this->resource; + } + + /** + * {@inheritdoc} + */ + public function seek($offset, $whence = SEEK_SET) + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot seek on a detached stream'); + } + + fseek($this->resource, $offset, $whence); + } + + /** + * {@inheritdoc} + */ + public function rewind() + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot rewind on a detached stream'); + } + + rewind($this->resource); + } + + /** + * {@inheritdoc} + */ + public function isWritable() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function write($string) + { + throw new \RuntimeException('Cannot write on this stream'); + } + + /** + * {@inheritdoc} + */ + public function isReadable() + { + return null !== $this->resource; + } + + /** + * {@inheritdoc} + */ + public function read($length) + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot read on a detached stream'); + } + + $read = ''; + + // First read from the resource + if (ftell($this->resource) !== $this->written) { + $read = fread($this->resource, $length); + } + + $bytesRead = strlen($read); + + if ($bytesRead < $length) { + $streamRead = $this->stream->read($length - $bytesRead); + + // Write on the underlying stream what we read + $this->written += fwrite($this->resource, $streamRead); + $read .= $streamRead; + } + + return $read; + } + + /** + * {@inheritdoc} + */ + public function getContents() + { + if (null === $this->resource) { + throw new \RuntimeException('Cannot read on a detached stream'); + } + + $read = ''; + + while (!$this->eof()) { + $read .= $this->read(8192); + } + + return $read; + } + + /** + * {@inheritdoc} + */ + public function getMetadata($key = null) + { + if (null === $this->resource) { + if (null === $key) { + return []; + } + + return; + } + + $metadata = stream_get_meta_data($this->resource); + + if (null === $key) { + return $metadata; + } + + if (!array_key_exists($key, $metadata)) { + return; + } + + return $metadata[$key]; + } +} diff --git a/www/multitube/vendor/php-http/message/src/StreamFactory/DiactorosStreamFactory.php b/www/multitube/vendor/php-http/message/src/StreamFactory/DiactorosStreamFactory.php new file mode 100644 index 0000000..8ae2b28 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/StreamFactory/DiactorosStreamFactory.php @@ -0,0 +1,48 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory + */ +final class DiactorosStreamFactory implements StreamFactory +{ + /** + * {@inheritdoc} + */ + public function createStream($body = null) + { + if ($body instanceof StreamInterface) { + return $body; + } + + if (is_resource($body)) { + if (class_exists(LaminasStream::class)) { + return new LaminasStream($body); + } + + return new ZendStream($body); + } + + if (class_exists(LaminasStream::class)) { + $stream = new LaminasStream('php://memory', 'rw'); + } else { + $stream = new ZendStream('php://memory', 'rw'); + } + + if (null !== $body && '' !== $body) { + $stream->write((string) $body); + } + + return $stream; + } +} diff --git a/www/multitube/vendor/php-http/message/src/StreamFactory/GuzzleStreamFactory.php b/www/multitube/vendor/php-http/message/src/StreamFactory/GuzzleStreamFactory.php new file mode 100644 index 0000000..9adeeb5 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/StreamFactory/GuzzleStreamFactory.php @@ -0,0 +1,23 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory + */ +final class GuzzleStreamFactory implements StreamFactory +{ + /** + * {@inheritdoc} + */ + public function createStream($body = null) + { + return \GuzzleHttp\Psr7\stream_for($body); + } +} diff --git a/www/multitube/vendor/php-http/message/src/StreamFactory/SlimStreamFactory.php b/www/multitube/vendor/php-http/message/src/StreamFactory/SlimStreamFactory.php new file mode 100644 index 0000000..9274aae --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/StreamFactory/SlimStreamFactory.php @@ -0,0 +1,39 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory + */ +final class SlimStreamFactory implements StreamFactory +{ + /** + * {@inheritdoc} + */ + public function createStream($body = null) + { + if ($body instanceof StreamInterface) { + return $body; + } + + if (is_resource($body)) { + return new Stream($body); + } + + $resource = fopen('php://memory', 'r+'); + $stream = new Stream($resource); + if (null !== $body && '' !== $body) { + $stream->write((string) $body); + } + + return $stream; + } +} diff --git a/www/multitube/vendor/php-http/message/src/UriFactory/DiactorosUriFactory.php b/www/multitube/vendor/php-http/message/src/UriFactory/DiactorosUriFactory.php new file mode 100644 index 0000000..be883de --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/UriFactory/DiactorosUriFactory.php @@ -0,0 +1,36 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Diactoros PSR-17 factory + */ +final class DiactorosUriFactory implements UriFactory +{ + /** + * {@inheritdoc} + */ + public function createUri($uri) + { + if ($uri instanceof UriInterface) { + return $uri; + } elseif (is_string($uri)) { + if (class_exists(LaminasUri::class)) { + return new LaminasUri($uri); + } + + return new ZendUri($uri); + } + + throw new \InvalidArgumentException('URI must be a string or UriInterface'); + } +} diff --git a/www/multitube/vendor/php-http/message/src/UriFactory/GuzzleUriFactory.php b/www/multitube/vendor/php-http/message/src/UriFactory/GuzzleUriFactory.php new file mode 100644 index 0000000..b16ca52 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/UriFactory/GuzzleUriFactory.php @@ -0,0 +1,24 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Guzzle PSR-17 factory + */ +final class GuzzleUriFactory implements UriFactory +{ + /** + * {@inheritdoc} + */ + public function createUri($uri) + { + return Psr7\uri_for($uri); + } +} diff --git a/www/multitube/vendor/php-http/message/src/UriFactory/SlimUriFactory.php b/www/multitube/vendor/php-http/message/src/UriFactory/SlimUriFactory.php new file mode 100644 index 0000000..e5bef03 --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/UriFactory/SlimUriFactory.php @@ -0,0 +1,33 @@ + + * + * @deprecated This will be removed in php-http/message2.0. Consider using the official Slim PSR-17 factory + */ +final class SlimUriFactory implements UriFactory +{ + /** + * {@inheritdoc} + */ + public function createUri($uri) + { + if ($uri instanceof UriInterface) { + return $uri; + } + + if (is_string($uri)) { + return Uri::createFromString($uri); + } + + throw new \InvalidArgumentException('URI must be a string or UriInterface'); + } +} diff --git a/www/multitube/vendor/php-http/message/src/filters.php b/www/multitube/vendor/php-http/message/src/filters.php new file mode 100644 index 0000000..15ed73d --- /dev/null +++ b/www/multitube/vendor/php-http/message/src/filters.php @@ -0,0 +1,6 @@ + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/README.md b/www/multitube/vendor/php-http/multipart-stream-builder/README.md new file mode 100644 index 0000000..764ff73 --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/README.md @@ -0,0 +1,38 @@ +# PSR-7 Multipart Stream Builder + +[![Latest Version](https://img.shields.io/github/release/php-http/multipart-stream-builder.svg?style=flat-square)](https://github.com/php-http/multipart-stream-builder/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/travis/php-http/multipart-stream-builder/master.svg?style=flat-square)](https://travis-ci.org/php-http/multipart-stream-builder) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/multipart-stream-builder.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/multipart-stream-builder) +[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/multipart-stream-builder.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/multipart-stream-builder) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/multipart-stream-builder.svg?style=flat-square)](https://packagist.org/packages/php-http/multipart-stream-builder) + +**A builder for Multipart PSR-7 Streams. The builder create streams independenly form any PSR-7 implementation.** + + +## Install + +Via Composer + +``` bash +$ composer require php-http/multipart-stream-builder +``` + +## Documentation + +Please see the [official documentation](http://php-http.readthedocs.org/en/latest/components/multipart-stream-builder.html). + + +## Contributing + +Please see [CONTRIBUTING](CONTRIBUTING.md) and [CONDUCT](CONDUCT.md) for details. + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/composer.json b/www/multitube/vendor/php-http/multipart-stream-builder/composer.json new file mode 100644 index 0000000..4bb275e --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/composer.json @@ -0,0 +1,44 @@ +{ + "name": "php-http/multipart-stream-builder", + "description": "A builder class that help you create a multipart stream", + "license": "MIT", + "keywords": ["http", "factory", "message", "stream", "multipart stream"], + "homepage": "http://php-http.org", + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com" + } + ], + "require": { + "php": "^7.1 || ^8.0", + "psr/http-message": "^1.0", + "psr/http-factory": "^1.0", + "php-http/message-factory": "^1.0.2", + "php-http/discovery": "^1.7" + }, + "require-dev": { + "phpunit/phpunit": "^7.5.15 || ^8.5 || ^9.3", + "php-http/message": "^1.5", + "nyholm/psr7": "^1.0" + }, + "autoload": { + "psr-4": { + "Http\\Message\\MultipartStream\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "tests\\Http\\Message\\MultipartStream\\": "tests/" + } + }, + "scripts": { + "test": "vendor/bin/phpunit", + "test-ci": "vendor/bin/phpunit --coverage-text --coverage-clover=build/coverage.xml" + }, + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + } +} diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php b/www/multitube/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php new file mode 100644 index 0000000..6e4ca66 --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/src/ApacheMimetypeHelper.php @@ -0,0 +1,142 @@ + + */ +class ApacheMimetypeHelper implements MimetypeHelper +{ + /** + * {@inheritdoc} + * + * @see http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types + */ + public function getMimetypeFromFilename($filename) + { + return $this->getMimetypeFromExtension(pathinfo($filename, PATHINFO_EXTENSION)); + } + + /** + * {@inheritdoc} + * + * @see http://svn.apache.org/repos/asf/httpd/httpd/branches/1.3.x/conf/mime.types + */ + public function getMimetypeFromExtension($extension) + { + static $mimetypes = [ + '7z' => 'application/x-7z-compressed', + 'aac' => 'audio/x-aac', + 'ai' => 'application/postscript', + 'aif' => 'audio/x-aiff', + 'asc' => 'text/plain', + 'asf' => 'video/x-ms-asf', + 'atom' => 'application/atom+xml', + 'avi' => 'video/x-msvideo', + 'bmp' => 'image/bmp', + 'bz2' => 'application/x-bzip2', + 'cer' => 'application/pkix-cert', + 'crl' => 'application/pkix-crl', + 'crt' => 'application/x-x509-ca-cert', + 'css' => 'text/css', + 'csv' => 'text/csv', + 'cu' => 'application/cu-seeme', + 'deb' => 'application/x-debian-package', + 'doc' => 'application/msword', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dvi' => 'application/x-dvi', + 'eot' => 'application/vnd.ms-fontobject', + 'eps' => 'application/postscript', + 'epub' => 'application/epub+zip', + 'etx' => 'text/x-setext', + 'flac' => 'audio/flac', + 'flv' => 'video/x-flv', + 'gif' => 'image/gif', + 'gz' => 'application/gzip', + 'htm' => 'text/html', + 'html' => 'text/html', + 'ico' => 'image/x-icon', + 'ics' => 'text/calendar', + 'ini' => 'text/plain', + 'iso' => 'application/x-iso9660-image', + 'jar' => 'application/java-archive', + 'jpe' => 'image/jpeg', + 'jpeg' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'js' => 'text/javascript', + 'json' => 'application/json', + 'latex' => 'application/x-latex', + 'log' => 'text/plain', + 'm4a' => 'audio/mp4', + 'm4v' => 'video/mp4', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mov' => 'video/quicktime', + 'mp3' => 'audio/mpeg', + 'mp4' => 'video/mp4', + 'mp4a' => 'audio/mp4', + 'mp4v' => 'video/mp4', + 'mpe' => 'video/mpeg', + 'mpeg' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mpg4' => 'video/mp4', + 'oga' => 'audio/ogg', + 'ogg' => 'audio/ogg', + 'ogv' => 'video/ogg', + 'ogx' => 'application/ogg', + 'pbm' => 'image/x-portable-bitmap', + 'pdf' => 'application/pdf', + 'pgm' => 'image/x-portable-graymap', + 'png' => 'image/png', + 'pnm' => 'image/x-portable-anymap', + 'ppm' => 'image/x-portable-pixmap', + 'ppt' => 'application/vnd.ms-powerpoint', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'ps' => 'application/postscript', + 'qt' => 'video/quicktime', + 'rar' => 'application/x-rar-compressed', + 'ras' => 'image/x-cmu-raster', + 'rss' => 'application/rss+xml', + 'rtf' => 'application/rtf', + 'sgm' => 'text/sgml', + 'sgml' => 'text/sgml', + 'svg' => 'image/svg+xml', + 'swf' => 'application/x-shockwave-flash', + 'tar' => 'application/x-tar', + 'tif' => 'image/tiff', + 'tiff' => 'image/tiff', + 'torrent' => 'application/x-bittorrent', + 'ttf' => 'application/x-font-ttf', + 'txt' => 'text/plain', + 'wav' => 'audio/x-wav', + 'webm' => 'video/webm', + 'wma' => 'audio/x-ms-wma', + 'wmv' => 'video/x-ms-wmv', + 'woff' => 'application/x-font-woff', + 'wsdl' => 'application/wsdl+xml', + 'xbm' => 'image/x-xbitmap', + 'xls' => 'application/vnd.ms-excel', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xml' => 'application/xml', + 'xpm' => 'image/x-xpixmap', + 'xwd' => 'image/x-xwindowdump', + 'yaml' => 'text/yaml', + 'yml' => 'text/yaml', + 'zip' => 'application/zip', + + // Non-Apache standard + 'pkpass' => 'application/vnd.apple.pkpass', + 'msg' => 'application/vnd.ms-outlook', + ]; + + $extension = strtolower($extension); + + return isset($mimetypes[$extension]) + ? $mimetypes[$extension] + : null; + } +} diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php b/www/multitube/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php new file mode 100644 index 0000000..9f3f0d9 --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/src/CustomMimetypeHelper.php @@ -0,0 +1,51 @@ + + */ +class CustomMimetypeHelper extends ApacheMimetypeHelper +{ + /** + * @var array + */ + private $mimetypes = []; + + /** + * @param array $mimetypes should be of type extension => mimetype + */ + public function __construct(array $mimetypes = []) + { + $this->mimetypes = $mimetypes; + } + + /** + * @param string $extension + * @param string $mimetype + * + * @return $this + */ + public function addMimetype($extension, $mimetype) + { + $this->mimetypes[$extension] = $mimetype; + + return $this; + } + + /** + * {@inheritdoc} + * + * Check if we have any defined mimetypes and of not fallback to ApacheMimetypeHelper + */ + public function getMimetypeFromExtension($extension) + { + $extension = strtolower($extension); + + return isset($this->mimetypes[$extension]) + ? $this->mimetypes[$extension] + : parent::getMimetypeFromExtension($extension); + } +} diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php b/www/multitube/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php new file mode 100644 index 0000000..fa7cf18 --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/src/MimetypeHelper.php @@ -0,0 +1,27 @@ + + */ +interface MimetypeHelper +{ + /** + * Determines the mimetype of a file by looking at its extension. + * + * @param string $filename + * + * @return null|string + */ + public function getMimetypeFromFilename($filename); + + /** + * Maps a file extensions to a mimetype. + * + * @param string $extension The file extension + * + * @return string|null + */ + public function getMimetypeFromExtension($extension); +} diff --git a/www/multitube/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php b/www/multitube/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php new file mode 100644 index 0000000..7eeb876 --- /dev/null +++ b/www/multitube/vendor/php-http/multipart-stream-builder/src/MultipartStreamBuilder.php @@ -0,0 +1,334 @@ + + */ +class MultipartStreamBuilder +{ + /** + * @var HttplugStreamFactory|StreamFactoryInterface + */ + private $streamFactory; + + /** + * @var MimetypeHelper + */ + private $mimetypeHelper; + + /** + * @var string + */ + private $boundary; + + /** + * @var array Element where each Element is an array with keys ['contents', 'headers', 'filename'] + */ + private $data = []; + + /** + * @param HttplugStreamFactory|StreamFactoryInterface|null $streamFactory + */ + public function __construct($streamFactory = null) + { + if ($streamFactory instanceof StreamFactoryInterface || $streamFactory instanceof HttplugStreamFactory) { + $this->streamFactory = $streamFactory; + + return; + } + + if (null !== $streamFactory) { + throw new \LogicException(sprintf( + 'First arguemnt to the constructor of "%s" must be of type "%s", "%s" or null. Got %s', + __CLASS__, + StreamFactoryInterface::class, + HttplugStreamFactory::class, + \is_object($streamFactory) ? \get_class($streamFactory) : \gettype($streamFactory) + )); + } + + // Try to find a stream factory. + try { + $this->streamFactory = Psr17FactoryDiscovery::findStreamFactory(); + } catch (NotFoundException $psr17Exception) { + try { + $this->streamFactory = StreamFactoryDiscovery::find(); + } catch (NotFoundException $httplugException) { + // we could not find any factory. + throw $psr17Exception; + } + } + } + + /** + * Add a resource to the Multipart Stream. + * + * @param string $name the formpost name + * @param string|resource|StreamInterface $resource + * @param array $options { + * + * @var array $headers additional headers ['header-name' => 'header-value'] + * @var string $filename + * } + * + * @return MultipartStreamBuilder + */ + public function addResource($name, $resource, array $options = []) + { + $stream = $this->createStream($resource); + + // validate options['headers'] exists + if (!isset($options['headers'])) { + $options['headers'] = []; + } + + // Try to add filename if it is missing + if (empty($options['filename'])) { + $options['filename'] = null; + $uri = $stream->getMetadata('uri'); + if ('php://' !== substr($uri, 0, 6)) { + $options['filename'] = $uri; + } + } + + $this->prepareHeaders($name, $stream, $options['filename'], $options['headers']); + $this->data[] = ['contents' => $stream, 'headers' => $options['headers'], 'filename' => $options['filename']]; + + return $this; + } + + /** + * Build the stream. + * + * @return StreamInterface + */ + public function build() + { + $streams = ''; + foreach ($this->data as $data) { + // Add start and headers + $streams .= "--{$this->getBoundary()}\r\n". + $this->getHeaders($data['headers'])."\r\n"; + + // Convert the stream to string + /* @var $contentStream StreamInterface */ + $contentStream = $data['contents']; + if ($contentStream->isSeekable()) { + $streams .= $contentStream->__toString(); + } else { + $streams .= $contentStream->getContents(); + } + + $streams .= "\r\n"; + } + + // Append end + $streams .= "--{$this->getBoundary()}--\r\n"; + + return $this->createStream($streams); + } + + /** + * Add extra headers if they are missing. + * + * @param string $name + * @param StreamInterface $stream + * @param string $filename + * @param array &$headers + */ + private function prepareHeaders($name, StreamInterface $stream, $filename, array &$headers) + { + $hasFilename = '0' === $filename || $filename; + + // Set a default content-disposition header if one was not provided + if (!$this->hasHeader($headers, 'content-disposition')) { + $headers['Content-Disposition'] = sprintf('form-data; name="%s"', $name); + if ($hasFilename) { + $headers['Content-Disposition'] .= sprintf('; filename="%s"', $this->basename($filename)); + } + } + + // Set a default content-length header if one was not provided + if (!$this->hasHeader($headers, 'content-length')) { + if ($length = $stream->getSize()) { + $headers['Content-Length'] = (string) $length; + } + } + + // Set a default Content-Type if one was not provided + if (!$this->hasHeader($headers, 'content-type') && $hasFilename) { + if ($type = $this->getMimetypeHelper()->getMimetypeFromFilename($filename)) { + $headers['Content-Type'] = $type; + } + } + } + + /** + * Get the headers formatted for the HTTP message. + * + * @param array $headers + * + * @return string + */ + private function getHeaders(array $headers) + { + $str = ''; + foreach ($headers as $key => $value) { + $str .= sprintf("%s: %s\r\n", $key, $value); + } + + return $str; + } + + /** + * Check if header exist. + * + * @param array $headers + * @param string $key case insensitive + * + * @return bool + */ + private function hasHeader(array $headers, $key) + { + $lowercaseHeader = strtolower($key); + foreach ($headers as $k => $v) { + if (strtolower($k) === $lowercaseHeader) { + return true; + } + } + + return false; + } + + /** + * Get the boundary that separates the streams. + * + * @return string + */ + public function getBoundary() + { + if (null === $this->boundary) { + $this->boundary = uniqid('', true); + } + + return $this->boundary; + } + + /** + * @param string $boundary + * + * @return MultipartStreamBuilder + */ + public function setBoundary($boundary) + { + $this->boundary = $boundary; + + return $this; + } + + /** + * @return MimetypeHelper + */ + private function getMimetypeHelper() + { + if (null === $this->mimetypeHelper) { + $this->mimetypeHelper = new ApacheMimetypeHelper(); + } + + return $this->mimetypeHelper; + } + + /** + * If you have custom file extension you may overwrite the default MimetypeHelper with your own. + * + * @param MimetypeHelper $mimetypeHelper + * + * @return MultipartStreamBuilder + */ + public function setMimetypeHelper(MimetypeHelper $mimetypeHelper) + { + $this->mimetypeHelper = $mimetypeHelper; + + return $this; + } + + /** + * Reset and clear all stored data. This allows you to use builder for a subsequent request. + * + * @return MultipartStreamBuilder + */ + public function reset() + { + $this->data = []; + $this->boundary = null; + + return $this; + } + + /** + * Gets the filename from a given path. + * + * PHP's basename() does not properly support streams or filenames beginning with a non-US-ASCII character. + * + * @author Drupal 8.2 + * + * @param string $path + * + * @return string + */ + private function basename($path) + { + $separators = '/'; + if (DIRECTORY_SEPARATOR != '/') { + // For Windows OS add special separator. + $separators .= DIRECTORY_SEPARATOR; + } + + // Remove right-most slashes when $path points to directory. + $path = rtrim($path, $separators); + + // Returns the trailing part of the $path starting after one of the directory separators. + $filename = preg_match('@[^'.preg_quote($separators, '@').']+$@', $path, $matches) ? $matches[0] : ''; + + return $filename; + } + + /** + * @param string|resource|StreamInterface $resource + * + * @return StreamInterface + */ + private function createStream($resource) + { + if ($resource instanceof StreamInterface) { + return $resource; + } + + if ($this->streamFactory instanceof HttplugStreamFactory) { + return $this->streamFactory->createStream($resource); + } + + // Assert: We are using a PSR17 stream factory. + if (\is_string($resource)) { + return $this->streamFactory->createStream($resource); + } + + if (\is_resource($resource)) { + return $this->streamFactory->createStreamFromResource($resource); + } + + throw new \InvalidArgumentException(sprintf('First argument to "%s::createStream()" must be a string, resource or StreamInterface.', __CLASS__)); + } +} diff --git a/www/multitube/vendor/php-http/promise/CHANGELOG.md b/www/multitube/vendor/php-http/promise/CHANGELOG.md new file mode 100644 index 0000000..479deb8 --- /dev/null +++ b/www/multitube/vendor/php-http/promise/CHANGELOG.md @@ -0,0 +1,48 @@ +# Change Log + +## 1.1.0 - 2020-07-07 + +### Added + +- Test with PHP 7.1, 7.2, 7.3, 7.4 and 8.0 + +### Removed + +- PHP 5 and 7.0 support + +### Fixed + +- Fixed PHPDoc for `Promise::then` + +## 1.0.0 - 2016-01-26 + +### Removed + +- PSR-7 dependency + + +## 1.0.0-RC1 - 2016-01-12 + +### Added + +- Tests for full coverage + +## Changed + +- Updated package files +- Clarified wait method behavior +- Contributing guide moved to the documentation + + +## 0.1.1 - 2015-12-24 + +## Added + +- Fulfilled and Rejected promise implementations + + +## 0.1.0 - 2015-12-13 + +## Added + +- Promise interface diff --git a/www/multitube/vendor/php-http/promise/LICENSE b/www/multitube/vendor/php-http/promise/LICENSE new file mode 100644 index 0000000..4558d6f --- /dev/null +++ b/www/multitube/vendor/php-http/promise/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2016 PHP HTTP Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/php-http/promise/README.md b/www/multitube/vendor/php-http/promise/README.md new file mode 100644 index 0000000..ee95e09 --- /dev/null +++ b/www/multitube/vendor/php-http/promise/README.md @@ -0,0 +1,48 @@ +# Promise + +[![Latest Version](https://img.shields.io/github/release/php-http/promise.svg?style=flat-square)](https://github.com/php-http/promise/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/travis/php-http/promise.svg?style=flat-square)](https://travis-ci.org/php-http/promise) +[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/php-http/promise.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/promise) +[![Quality Score](https://img.shields.io/scrutinizer/g/php-http/promise.svg?style=flat-square)](https://scrutinizer-ci.com/g/php-http/promise) +[![Total Downloads](https://img.shields.io/packagist/dt/php-http/promise.svg?style=flat-square)](https://packagist.org/packages/php-http/promise) + +**Promise used for asynchronous HTTP requests.** + +**Note:** This will eventually be removed/deprecated and replaced with the upcoming Promise PSR. + + +## Install + +Via Composer + +``` bash +$ composer require php-http/promise +``` + + +## Documentation + +Please see the [official documentation](http://docs.php-http.org/en/latest/components/promise.html). + + +## Testing + +``` bash +$ composer test +``` + + +## Contributing + +Please see our [contributing guide](http://docs.php-http.org/en/latest/development/contributing.html). + + +## Security + +If you discover any security related issues, please contact us at [security@php-http.org](mailto:security@php-http.org). + + +## License + +The MIT License (MIT). Please see [License File](LICENSE) for more information. diff --git a/www/multitube/vendor/php-http/promise/composer.json b/www/multitube/vendor/php-http/promise/composer.json new file mode 100644 index 0000000..812167b --- /dev/null +++ b/www/multitube/vendor/php-http/promise/composer.json @@ -0,0 +1,38 @@ +{ + "name": "php-http/promise", + "description": "Promise used for asynchronous HTTP requests", + "license": "MIT", + "keywords": ["promise"], + "homepage": "http://httplug.io", + "authors": [ + { + "name": "Joel Wurtz", + "email": "joel.wurtz@gmail.com" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com" + } + ], + "require": { + "php" : "^7.1 || ^8.0" + }, + "require-dev": { + "friends-of-phpspec/phpspec-code-coverage" : "^4.3.2", + "phpspec/phpspec": "^5.1.2 || ^6.2" + }, + "autoload": { + "psr-4": { + "Http\\Promise\\": "src/" + } + }, + "scripts": { + "test": "vendor/bin/phpspec run", + "test-ci": "vendor/bin/phpspec run -c phpspec.yml.ci" + }, + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + } +} diff --git a/www/multitube/vendor/php-http/promise/src/FulfilledPromise.php b/www/multitube/vendor/php-http/promise/src/FulfilledPromise.php new file mode 100644 index 0000000..f60f686 --- /dev/null +++ b/www/multitube/vendor/php-http/promise/src/FulfilledPromise.php @@ -0,0 +1,58 @@ + + */ +final class FulfilledPromise implements Promise +{ + /** + * @var mixed + */ + private $result; + + /** + * @param $result + */ + public function __construct($result) + { + $this->result = $result; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onFulfilled) { + return $this; + } + + try { + return new self($onFulfilled($this->result)); + } catch (\Exception $e) { + return new RejectedPromise($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::FULFILLED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + return $this->result; + } + } +} diff --git a/www/multitube/vendor/php-http/promise/src/Promise.php b/www/multitube/vendor/php-http/promise/src/Promise.php new file mode 100644 index 0000000..3258ed0 --- /dev/null +++ b/www/multitube/vendor/php-http/promise/src/Promise.php @@ -0,0 +1,69 @@ + + * @author Márk Sági-Kazár + */ +interface Promise +{ + /** + * Promise has not been fulfilled or rejected. + */ + const PENDING = 'pending'; + + /** + * Promise has been fulfilled. + */ + const FULFILLED = 'fulfilled'; + + /** + * Promise has been rejected. + */ + const REJECTED = 'rejected'; + + /** + * Adds behavior for when the promise is resolved or rejected (response will be available, or error happens). + * + * If you do not care about one of the cases, you can set the corresponding callable to null + * The callback will be called when the value arrived and never more than once. + * + * @param callable|null $onFulfilled called when a response will be available + * @param callable|null $onRejected called when an exception occurs + * + * @return Promise a new resolved promise with value of the executed callback (onFulfilled / onRejected) + */ + public function then(callable $onFulfilled = null, callable $onRejected = null); + + /** + * Returns the state of the promise, one of PENDING, FULFILLED or REJECTED. + * + * @return string + */ + public function getState(); + + /** + * Wait for the promise to be fulfilled or rejected. + * + * When this method returns, the request has been resolved and if callables have been + * specified, the appropriate one has terminated. + * + * When $unwrap is true (the default), the response is returned, or the exception thrown + * on failure. Otherwise, nothing is returned or thrown. + * + * @param bool $unwrap Whether to return resolved value / throw reason or not + * + * @return mixed Resolved value, null if $unwrap is set to false + * + * @throws \Exception the rejection reason if $unwrap is set to true and the request failed + */ + public function wait($unwrap = true); +} diff --git a/www/multitube/vendor/php-http/promise/src/RejectedPromise.php b/www/multitube/vendor/php-http/promise/src/RejectedPromise.php new file mode 100644 index 0000000..e396a40 --- /dev/null +++ b/www/multitube/vendor/php-http/promise/src/RejectedPromise.php @@ -0,0 +1,58 @@ + + */ +final class RejectedPromise implements Promise +{ + /** + * @var \Exception + */ + private $exception; + + /** + * @param \Exception $exception + */ + public function __construct(\Exception $exception) + { + $this->exception = $exception; + } + + /** + * {@inheritdoc} + */ + public function then(callable $onFulfilled = null, callable $onRejected = null) + { + if (null === $onRejected) { + return $this; + } + + try { + return new FulfilledPromise($onRejected($this->exception)); + } catch (\Exception $e) { + return new self($e); + } + } + + /** + * {@inheritdoc} + */ + public function getState() + { + return Promise::REJECTED; + } + + /** + * {@inheritdoc} + */ + public function wait($unwrap = true) + { + if ($unwrap) { + throw $this->exception; + } + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/.travis.yml b/www/multitube/vendor/phpdocumentor/reflection-common/.travis.yml new file mode 100644 index 0000000..958ecf8 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/.travis.yml @@ -0,0 +1,35 @@ +language: php +php: + - 5.5 + - 5.6 + - 7.0 + - 7.1 + - hhvm + - nightly + +matrix: + allow_failures: + - php: + - hhvm + - nightly + +cache: + directories: + - $HOME/.composer/cache + +script: + - vendor/bin/phpunit --coverage-clover=coverage.clover -v + - composer update --no-interaction --prefer-source + - vendor/bin/phpunit -v + +before_script: + - composer install --no-interaction + +after_script: + - if [ $TRAVIS_PHP_VERSION = '5.6' ]; then wget https://scrutinizer-ci.com/ocular.phar; php ocular.phar code-coverage:upload --format=php-clover coverage.clover; fi + +notifications: + irc: "irc.freenode.org#phpdocumentor" + email: + - me@mikevanriel.com + - ashnazg@php.net diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/LICENSE b/www/multitube/vendor/phpdocumentor/reflection-common/LICENSE new file mode 100644 index 0000000..ed6926c --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 phpDocumentor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/README.md b/www/multitube/vendor/phpdocumentor/reflection-common/README.md new file mode 100644 index 0000000..68a80c8 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/README.md @@ -0,0 +1,2 @@ +# ReflectionCommon +[![Build Status](https://travis-ci.org/phpDocumentor/ReflectionCommon.svg?branch=master)](https://travis-ci.org/phpDocumentor/ReflectionCommon) diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/composer.json b/www/multitube/vendor/phpdocumentor/reflection-common/composer.json new file mode 100644 index 0000000..90eee0f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/composer.json @@ -0,0 +1,29 @@ +{ + "name": "phpdocumentor/reflection-common", + "keywords": ["phpdoc", "phpDocumentor", "reflection", "static analysis", "FQSEN"], + "homepage": "http://www.phpdoc.org", + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "license": "MIT", + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "require": { + "php": ">=5.5" + }, + "autoload" : { + "psr-4" : { + "phpDocumentor\\Reflection\\": ["src"] + } + }, + "require-dev": { + "phpunit/phpunit": "^4.6" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/src/Element.php b/www/multitube/vendor/phpdocumentor/reflection-common/src/Element.php new file mode 100644 index 0000000..712e30e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/src/Element.php @@ -0,0 +1,32 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +/** + * Interface for files processed by the ProjectFactory + */ +interface File +{ + /** + * Returns the content of the file as a string. + * + * @return string + */ + public function getContents(); + + /** + * Returns md5 hash of the file. + * + * @return string + */ + public function md5(); + + /** + * Returns an relative path to the file. + * + * @return string + */ + public function path(); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/src/Fqsen.php b/www/multitube/vendor/phpdocumentor/reflection-common/src/Fqsen.php new file mode 100644 index 0000000..ce88d03 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/src/Fqsen.php @@ -0,0 +1,82 @@ +fqsen = $fqsen; + + if (isset($matches[2])) { + $this->name = $matches[2]; + } else { + $matches = explode('\\', $fqsen); + $this->name = trim(end($matches), '()'); + } + } + + /** + * converts this class to string. + * + * @return string + */ + public function __toString() + { + return $this->fqsen; + } + + /** + * Returns the name of the element without path. + * + * @return string + */ + public function getName() + { + return $this->name; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/src/Location.php b/www/multitube/vendor/phpdocumentor/reflection-common/src/Location.php new file mode 100644 index 0000000..5760321 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/src/Location.php @@ -0,0 +1,57 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +/** + * The location where an element occurs within a file. + */ +final class Location +{ + /** @var int */ + private $lineNumber = 0; + + /** @var int */ + private $columnNumber = 0; + + /** + * Initializes the location for an element using its line number in the file and optionally the column number. + * + * @param int $lineNumber + * @param int $columnNumber + */ + public function __construct($lineNumber, $columnNumber = 0) + { + $this->lineNumber = $lineNumber; + $this->columnNumber = $columnNumber; + } + + /** + * Returns the line number that is covered by this location. + * + * @return integer + */ + public function getLineNumber() + { + return $this->lineNumber; + } + + /** + * Returns the column number (character position on a line) for this location object. + * + * @return integer + */ + public function getColumnNumber() + { + return $this->columnNumber; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-common/src/Project.php b/www/multitube/vendor/phpdocumentor/reflection-common/src/Project.php new file mode 100644 index 0000000..3ed1e39 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-common/src/Project.php @@ -0,0 +1,25 @@ + **Note**: *this is a core component of phpDocumentor and is constantly being +> optimized for performance.* + +Installation +------------ + +You can install the component in the following ways: + +* Use the official Github repository (https://github.com/phpDocumentor/ReflectionDocBlock) +* Via Composer (http://packagist.org/packages/phpdocumentor/reflection-docblock) + +Usage +----- + +In order to parse the DocBlock one needs a DocBlockFactory that can be +instantiated using its `createInstance` factory method like this: + +```php +$factory = \phpDocumentor\Reflection\DocBlockFactory::createInstance(); +``` + +Then we can use the `create` method of the factory to interpret the DocBlock. +Please note that it is also possible to provide a class that has the +`getDocComment()` method, such as an object of type `ReflectionClass`, the +create method will read that if it exists. + +```php +$docComment = <<create($docComment); +``` + +The `create` method will yield an object of type `\phpDocumentor\Reflection\DocBlock` +whose methods can be queried as shown in the following example. + +```php +// Should contain the summary for this DocBlock +$summary = $docblock->getSummary(); + +// Contains an object of type \phpDocumentor\Reflection\DocBlock\Description; +// you can either cast it to string or use the render method to get a string +// representation of the Description. +$description = $docblock->getDescription(); +``` + +> For more examples it would be best to review the scripts in the `/examples` +> folder. + diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/composer.json b/www/multitube/vendor/phpdocumentor/reflection-docblock/composer.json new file mode 100644 index 0000000..78c6851 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/composer.json @@ -0,0 +1,28 @@ +{ + "name": "phpdocumentor/reflection-docblock", + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "require": { + "php": "^5.6 || ^7.0", + "phpdocumentor/reflection-common": "^1.0.0", + "phpdocumentor/type-resolver": "^0.4.0", + "webmozart/assert": "^1.0" + }, + "autoload": { + "psr-4": {"phpDocumentor\\Reflection\\": ["src/"]} + }, + "autoload-dev": { + "psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]} + }, + "require-dev": { + "mockery/mockery": "^0.9.4", + "phpunit/phpunit": "^4.4" + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php new file mode 100644 index 0000000..3991140 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock.php @@ -0,0 +1,220 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +use phpDocumentor\Reflection\DocBlock\Tag; +use Webmozart\Assert\Assert; + +final class DocBlock +{ + /** @var string The opening line for this docblock. */ + private $summary = ''; + + /** @var DocBlock\Description The actual description for this docblock. */ + private $description = null; + + /** @var Tag[] An array containing all the tags in this docblock; except inline. */ + private $tags = array(); + + /** @var Types\Context Information about the context of this DocBlock. */ + private $context = null; + + /** @var Location Information about the location of this DocBlock. */ + private $location = null; + + /** @var bool Is this DocBlock (the start of) a template? */ + private $isTemplateStart = false; + + /** @var bool Does this DocBlock signify the end of a DocBlock template? */ + private $isTemplateEnd = false; + + /** + * @param string $summary + * @param DocBlock\Description $description + * @param DocBlock\Tag[] $tags + * @param Types\Context $context The context in which the DocBlock occurs. + * @param Location $location The location within the file that this DocBlock occurs in. + * @param bool $isTemplateStart + * @param bool $isTemplateEnd + */ + public function __construct( + $summary = '', + DocBlock\Description $description = null, + array $tags = [], + Types\Context $context = null, + Location $location = null, + $isTemplateStart = false, + $isTemplateEnd = false + ) + { + Assert::string($summary); + Assert::boolean($isTemplateStart); + Assert::boolean($isTemplateEnd); + Assert::allIsInstanceOf($tags, Tag::class); + + $this->summary = $summary; + $this->description = $description ?: new DocBlock\Description(''); + foreach ($tags as $tag) { + $this->addTag($tag); + } + + $this->context = $context; + $this->location = $location; + + $this->isTemplateEnd = $isTemplateEnd; + $this->isTemplateStart = $isTemplateStart; + } + + /** + * @return string + */ + public function getSummary() + { + return $this->summary; + } + + /** + * @return DocBlock\Description + */ + public function getDescription() + { + return $this->description; + } + + /** + * Returns the current context. + * + * @return Types\Context + */ + public function getContext() + { + return $this->context; + } + + /** + * Returns the current location. + * + * @return Location + */ + public function getLocation() + { + return $this->location; + } + + /** + * Returns whether this DocBlock is the start of a Template section. + * + * A Docblock may serve as template for a series of subsequent DocBlocks. This is indicated by a special marker + * (`#@+`) that is appended directly after the opening `/**` of a DocBlock. + * + * An example of such an opening is: + * + * ``` + * /**#@+ + * * My DocBlock + * * / + * ``` + * + * The description and tags (not the summary!) are copied onto all subsequent DocBlocks and also applied to all + * elements that follow until another DocBlock is found that contains the closing marker (`#@-`). + * + * @see self::isTemplateEnd() for the check whether a closing marker was provided. + * + * @return boolean + */ + public function isTemplateStart() + { + return $this->isTemplateStart; + } + + /** + * Returns whether this DocBlock is the end of a Template section. + * + * @see self::isTemplateStart() for a more complete description of the Docblock Template functionality. + * + * @return boolean + */ + public function isTemplateEnd() + { + return $this->isTemplateEnd; + } + + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags() + { + return $this->tags; + } + + /** + * Returns an array of tags matching the given name. If no tags are found + * an empty array is returned. + * + * @param string $name String to search by. + * + * @return Tag[] + */ + public function getTagsByName($name) + { + Assert::string($name); + + $result = array(); + + /** @var Tag $tag */ + foreach ($this->getTags() as $tag) { + if ($tag->getName() != $name) { + continue; + } + + $result[] = $tag; + } + + return $result; + } + + /** + * Checks if a tag of a certain type is present in this DocBlock. + * + * @param string $name Tag name to check for. + * + * @return bool + */ + public function hasTag($name) + { + Assert::string($name); + + /** @var Tag $tag */ + foreach ($this->getTags() as $tag) { + if ($tag->getName() == $name) { + return true; + } + } + + return false; + } + + /** + * Adds a tag to this DocBlock. + * + * @param Tag $tag The tag to add. + * + * @return void + */ + private function addTag(Tag $tag) + { + $this->tags[] = $tag; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php new file mode 100644 index 0000000..c63cae5 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Description.php @@ -0,0 +1,113 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter; +use Webmozart\Assert\Assert; + +/** + * Object representing to description for a DocBlock. + * + * A Description object can consist of plain text but can also include tags. A Description Formatter can then combine + * a body template with sprintf-style placeholders together with formatted tags in order to reconstitute a complete + * description text using the format that you would prefer. + * + * Because parsing a Description text can be a verbose process this is handled by the {@see DescriptionFactory}. It is + * thus recommended to use that to create a Description object, like this: + * + * $description = $descriptionFactory->create('This is a {@see Description}', $context); + * + * The description factory will interpret the given body and create a body template and list of tags from them, and pass + * that onto the constructor if this class. + * + * > The $context variable is a class of type {@see \phpDocumentor\Reflection\Types\Context} and contains the namespace + * > and the namespace aliases that apply to this DocBlock. These are used by the Factory to resolve and expand partial + * > type names and FQSENs. + * + * If you do not want to use the DescriptionFactory you can pass a body template and tag listing like this: + * + * $description = new Description( + * 'This is a %1$s', + * [ new See(new Fqsen('\phpDocumentor\Reflection\DocBlock\Description')) ] + * ); + * + * It is generally recommended to use the Factory as that will also apply escaping rules, while the Description object + * is mainly responsible for rendering. + * + * @see DescriptionFactory to create a new Description. + * @see Description\Formatter for the formatting of the body and tags. + */ +class Description +{ + /** @var string */ + private $bodyTemplate; + + /** @var Tag[] */ + private $tags; + + /** + * Initializes a Description with its body (template) and a listing of the tags used in the body template. + * + * @param string $bodyTemplate + * @param Tag[] $tags + */ + public function __construct($bodyTemplate, array $tags = []) + { + Assert::string($bodyTemplate); + + $this->bodyTemplate = $bodyTemplate; + $this->tags = $tags; + } + + /** + * Returns the tags for this DocBlock. + * + * @return Tag[] + */ + public function getTags() + { + return $this->tags; + } + + /** + * Renders this description as a string where the provided formatter will format the tags in the expected string + * format. + * + * @param Formatter|null $formatter + * + * @return string + */ + public function render(Formatter $formatter = null) + { + if ($formatter === null) { + $formatter = new PassthroughFormatter(); + } + + $tags = []; + foreach ($this->tags as $tag) { + $tags[] = '{' . $formatter->format($tag) . '}'; + } + return vsprintf($this->bodyTemplate, $tags); + } + + /** + * Returns a plain string representation of this description. + * + * @return string + */ + public function __toString() + { + return $this->render(); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php new file mode 100644 index 0000000..f34d0f7 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/DescriptionFactory.php @@ -0,0 +1,192 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\Types\Context as TypeContext; + +/** + * Creates a new Description object given a body of text. + * + * Descriptions in phpDocumentor are somewhat complex entities as they can contain one or more tags inside their + * body that can be replaced with a readable output. The replacing is done by passing a Formatter object to the + * Description object's `render` method. + * + * In addition to the above does a Description support two types of escape sequences: + * + * 1. `{@}` to escape the `@` character to prevent it from being interpreted as part of a tag, i.e. `{{@}link}` + * 2. `{}` to escape the `}` character, this can be used if you want to use the `}` character in the description + * of an inline tag. + * + * If a body consists of multiple lines then this factory will also remove any superfluous whitespace at the beginning + * of each line while maintaining any indentation that is used. This will prevent formatting parsers from tripping + * over unexpected spaces as can be observed with tag descriptions. + */ +class DescriptionFactory +{ + /** @var TagFactory */ + private $tagFactory; + + /** + * Initializes this factory with the means to construct (inline) tags. + * + * @param TagFactory $tagFactory + */ + public function __construct(TagFactory $tagFactory) + { + $this->tagFactory = $tagFactory; + } + + /** + * Returns the parsed text of this description. + * + * @param string $contents + * @param TypeContext $context + * + * @return Description + */ + public function create($contents, TypeContext $context = null) + { + list($text, $tags) = $this->parse($this->lex($contents), $context); + + return new Description($text, $tags); + } + + /** + * Strips the contents from superfluous whitespace and splits the description into a series of tokens. + * + * @param string $contents + * + * @return string[] A series of tokens of which the description text is composed. + */ + private function lex($contents) + { + $contents = $this->removeSuperfluousStartingWhitespace($contents); + + // performance optimalization; if there is no inline tag, don't bother splitting it up. + if (strpos($contents, '{@') === false) { + return [$contents]; + } + + return preg_split( + '/\{ + # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. + (?!@\}) + # We want to capture the whole tag line, but without the inline tag delimiters. + (\@ + # Match everything up to the next delimiter. + [^{}]* + # Nested inline tag content should not be captured, or it will appear in the result separately. + (?: + # Match nested inline tags. + (?: + # Because we did not catch the tag delimiters earlier, we must be explicit with them here. + # Notice that this also matches "{}", as a way to later introduce it as an escape sequence. + \{(?1)?\} + | + # Make sure we match hanging "{". + \{ + ) + # Match content after the nested inline tag. + [^{}]* + )* # If there are more inline tags, match them as well. We use "*" since there may not be any + # nested inline tags. + ) + \}/Sux', + $contents, + null, + PREG_SPLIT_DELIM_CAPTURE + ); + } + + /** + * Parses the stream of tokens in to a new set of tokens containing Tags. + * + * @param string[] $tokens + * @param TypeContext $context + * + * @return string[]|Tag[] + */ + private function parse($tokens, TypeContext $context) + { + $count = count($tokens); + $tagCount = 0; + $tags = []; + + for ($i = 1; $i < $count; $i += 2) { + $tags[] = $this->tagFactory->create($tokens[$i], $context); + $tokens[$i] = '%' . ++$tagCount . '$s'; + } + + //In order to allow "literal" inline tags, the otherwise invalid + //sequence "{@}" is changed to "@", and "{}" is changed to "}". + //"%" is escaped to "%%" because of vsprintf. + //See unit tests for examples. + for ($i = 0; $i < $count; $i += 2) { + $tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]); + } + + return [implode('', $tokens), $tags]; + } + + /** + * Removes the superfluous from a multi-line description. + * + * When a description has more than one line then it can happen that the second and subsequent lines have an + * additional indentation. This is commonly in use with tags like this: + * + * {@}since 1.1.0 This is an example + * description where we have an + * indentation in the second and + * subsequent lines. + * + * If we do not normalize the indentation then we have superfluous whitespace on the second and subsequent + * lines and this may cause rendering issues when, for example, using a Markdown converter. + * + * @param string $contents + * + * @return string + */ + private function removeSuperfluousStartingWhitespace($contents) + { + $lines = explode("\n", $contents); + + // if there is only one line then we don't have lines with superfluous whitespace and + // can use the contents as-is + if (count($lines) <= 1) { + return $contents; + } + + // determine how many whitespace characters need to be stripped + $startingSpaceCount = 9999999; + for ($i = 1; $i < count($lines); $i++) { + // lines with a no length do not count as they are not indented at all + if (strlen(trim($lines[$i])) === 0) { + continue; + } + + // determine the number of prefixing spaces by checking the difference in line length before and after + // an ltrim + $startingSpaceCount = min($startingSpaceCount, strlen($lines[$i]) - strlen(ltrim($lines[$i]))); + } + + // strip the number of spaces from each line + if ($startingSpaceCount > 0) { + for ($i = 1; $i < count($lines); $i++) { + $lines[$i] = substr($lines[$i], $startingSpaceCount); + } + } + + return implode("\n", $lines); + } + +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php new file mode 100644 index 0000000..ea79f7c --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/ExampleFinder.php @@ -0,0 +1,170 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\DocBlock\Tags\Example; + +/** + * Class used to find an example file's location based on a given ExampleDescriptor. + */ +class ExampleFinder +{ + /** @var string */ + private $sourceDirectory = ''; + + /** @var string[] */ + private $exampleDirectories = array(); + + /** + * Attempts to find the example contents for the given descriptor. + * + * @param Example $example + * + * @return string + */ + public function find(Example $example) + { + $filename = $example->getFilePath(); + + $file = $this->getExampleFileContents($filename); + if (!$file) { + return "** File not found : {$filename} **"; + } + + return implode('', array_slice($file, $example->getStartingLine() - 1, $example->getLineCount())); + } + + /** + * Registers the project's root directory where an 'examples' folder can be expected. + * + * @param string $directory + * + * @return void + */ + public function setSourceDirectory($directory = '') + { + $this->sourceDirectory = $directory; + } + + /** + * Returns the project's root directory where an 'examples' folder can be expected. + * + * @return string + */ + public function getSourceDirectory() + { + return $this->sourceDirectory; + } + + /** + * Registers a series of directories that may contain examples. + * + * @param string[] $directories + */ + public function setExampleDirectories(array $directories) + { + $this->exampleDirectories = $directories; + } + + /** + * Returns a series of directories that may contain examples. + * + * @return string[] + */ + public function getExampleDirectories() + { + return $this->exampleDirectories; + } + + /** + * Attempts to find the requested example file and returns its contents or null if no file was found. + * + * This method will try several methods in search of the given example file, the first one it encounters is + * returned: + * + * 1. Iterates through all examples folders for the given filename + * 2. Checks the source folder for the given filename + * 3. Checks the 'examples' folder in the current working directory for examples + * 4. Checks the path relative to the current working directory for the given filename + * + * @param string $filename + * + * @return string|null + */ + private function getExampleFileContents($filename) + { + $normalizedPath = null; + + foreach ($this->exampleDirectories as $directory) { + $exampleFileFromConfig = $this->constructExamplePath($directory, $filename); + if (is_readable($exampleFileFromConfig)) { + $normalizedPath = $exampleFileFromConfig; + break; + } + } + + if (!$normalizedPath) { + if (is_readable($this->getExamplePathFromSource($filename))) { + $normalizedPath = $this->getExamplePathFromSource($filename); + } elseif (is_readable($this->getExamplePathFromExampleDirectory($filename))) { + $normalizedPath = $this->getExamplePathFromExampleDirectory($filename); + } elseif (is_readable($filename)) { + $normalizedPath = $filename; + } + } + + return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null; + } + + /** + * Get example filepath based on the example directory inside your project. + * + * @param string $file + * + * @return string + */ + private function getExamplePathFromExampleDirectory($file) + { + return getcwd() . DIRECTORY_SEPARATOR . 'examples' . DIRECTORY_SEPARATOR . $file; + } + + /** + * Returns a path to the example file in the given directory.. + * + * @param string $directory + * @param string $file + * + * @return string + */ + private function constructExamplePath($directory, $file) + { + return rtrim($directory, '\\/') . DIRECTORY_SEPARATOR . $file; + } + + /** + * Get example filepath based on sourcecode. + * + * @param string $file + * + * @return string + */ + private function getExamplePathFromSource($file) + { + return sprintf( + '%s%s%s', + trim($this->getSourceDirectory(), '\\/'), + DIRECTORY_SEPARATOR, + trim($file, '"') + ); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php new file mode 100644 index 0000000..e0faacb --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Serializer.php @@ -0,0 +1,148 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\DocBlock; +use Webmozart\Assert\Assert; + +/** + * Converts a DocBlock back from an object to a complete DocComment including Asterisks. + */ +class Serializer +{ + /** @var string The string to indent the comment with. */ + protected $indentString = ' '; + + /** @var int The number of times the indent string is repeated. */ + protected $indent = 0; + + /** @var bool Whether to indent the first line with the given indent amount and string. */ + protected $isFirstLineIndented = true; + + /** @var int|null The max length of a line. */ + protected $lineLength = null; + + /** @var DocBlock\Tags\Formatter A custom tag formatter. */ + protected $tagFormatter = null; + + /** + * Create a Serializer instance. + * + * @param int $indent The number of times the indent string is repeated. + * @param string $indentString The string to indent the comment with. + * @param bool $indentFirstLine Whether to indent the first line. + * @param int|null $lineLength The max length of a line or NULL to disable line wrapping. + * @param DocBlock\Tags\Formatter $tagFormatter A custom tag formatter, defaults to PassthroughFormatter. + */ + public function __construct($indent = 0, $indentString = ' ', $indentFirstLine = true, $lineLength = null, $tagFormatter = null) + { + Assert::integer($indent); + Assert::string($indentString); + Assert::boolean($indentFirstLine); + Assert::nullOrInteger($lineLength); + Assert::nullOrIsInstanceOf($tagFormatter, 'phpDocumentor\Reflection\DocBlock\Tags\Formatter'); + + $this->indent = $indent; + $this->indentString = $indentString; + $this->isFirstLineIndented = $indentFirstLine; + $this->lineLength = $lineLength; + $this->tagFormatter = $tagFormatter ?: new DocBlock\Tags\Formatter\PassthroughFormatter(); + } + + /** + * Generate a DocBlock comment. + * + * @param DocBlock $docblock The DocBlock to serialize. + * + * @return string The serialized doc block. + */ + public function getDocComment(DocBlock $docblock) + { + $indent = str_repeat($this->indentString, $this->indent); + $firstIndent = $this->isFirstLineIndented ? $indent : ''; + // 3 === strlen(' * ') + $wrapLength = $this->lineLength ? $this->lineLength - strlen($indent) - 3 : null; + + $text = $this->removeTrailingSpaces( + $indent, + $this->addAsterisksForEachLine( + $indent, + $this->getSummaryAndDescriptionTextBlock($docblock, $wrapLength) + ) + ); + + $comment = "{$firstIndent}/**\n{$indent} * {$text}\n{$indent} *\n"; + $comment = $this->addTagBlock($docblock, $wrapLength, $indent, $comment); + $comment .= $indent . ' */'; + + return $comment; + } + + /** + * @param $indent + * @param $text + * @return mixed + */ + private function removeTrailingSpaces($indent, $text) + { + return str_replace("\n{$indent} * \n", "\n{$indent} *\n", $text); + } + + /** + * @param $indent + * @param $text + * @return mixed + */ + private function addAsterisksForEachLine($indent, $text) + { + return str_replace("\n", "\n{$indent} * ", $text); + } + + /** + * @param DocBlock $docblock + * @param $wrapLength + * @return string + */ + private function getSummaryAndDescriptionTextBlock(DocBlock $docblock, $wrapLength) + { + $text = $docblock->getSummary() . ((string)$docblock->getDescription() ? "\n\n" . $docblock->getDescription() + : ''); + if ($wrapLength !== null) { + $text = wordwrap($text, $wrapLength); + return $text; + } + return $text; + } + + /** + * @param DocBlock $docblock + * @param $wrapLength + * @param $indent + * @param $comment + * @return string + */ + private function addTagBlock(DocBlock $docblock, $wrapLength, $indent, $comment) + { + foreach ($docblock->getTags() as $tag) { + $tagText = $this->tagFormatter->format($tag); + if ($wrapLength !== null) { + $tagText = wordwrap($tagText, $wrapLength); + } + $tagText = str_replace("\n", "\n{$indent} * ", $tagText); + + $comment .= "{$indent} * {$tagText}\n"; + } + + return $comment; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php new file mode 100644 index 0000000..8efd84e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/StandardTagFactory.php @@ -0,0 +1,320 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod; +use phpDocumentor\Reflection\DocBlock\Tags\Generic; +use phpDocumentor\Reflection\FqsenResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Creates a Tag object given the contents of a tag. + * + * This Factory is capable of determining the appropriate class for a tag and instantiate it using its `create` + * factory method. The `create` factory method of a Tag can have a variable number of arguments; this way you can + * pass the dependencies that you need to construct a tag object. + * + * > Important: each parameter in addition to the body variable for the `create` method must default to null, otherwise + * > it violates the constraint with the interface; it is recommended to use the {@see Assert::notNull()} method to + * > verify that a dependency is actually passed. + * + * This Factory also features a Service Locator component that is used to pass the right dependencies to the + * `create` method of a tag; each dependency should be registered as a service or as a parameter. + * + * When you want to use a Tag of your own with custom handling you need to call the `registerTagHandler` method, pass + * the name of the tag and a Fully Qualified Class Name pointing to a class that implements the Tag interface. + */ +final class StandardTagFactory implements TagFactory +{ + /** PCRE regular expression matching a tag name. */ + const REGEX_TAGNAME = '[\w\-\_\\\\]+'; + + /** + * @var string[] An array with a tag as a key, and an FQCN to a class that handles it as an array value. + */ + private $tagHandlerMappings = [ + 'author' => '\phpDocumentor\Reflection\DocBlock\Tags\Author', + 'covers' => '\phpDocumentor\Reflection\DocBlock\Tags\Covers', + 'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tags\Deprecated', + // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', + 'link' => '\phpDocumentor\Reflection\DocBlock\Tags\Link', + 'method' => '\phpDocumentor\Reflection\DocBlock\Tags\Method', + 'param' => '\phpDocumentor\Reflection\DocBlock\Tags\Param', + 'property-read' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead', + 'property' => '\phpDocumentor\Reflection\DocBlock\Tags\Property', + 'property-write' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite', + 'return' => '\phpDocumentor\Reflection\DocBlock\Tags\Return_', + 'see' => '\phpDocumentor\Reflection\DocBlock\Tags\See', + 'since' => '\phpDocumentor\Reflection\DocBlock\Tags\Since', + 'source' => '\phpDocumentor\Reflection\DocBlock\Tags\Source', + 'throw' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', + 'throws' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', + 'uses' => '\phpDocumentor\Reflection\DocBlock\Tags\Uses', + 'var' => '\phpDocumentor\Reflection\DocBlock\Tags\Var_', + 'version' => '\phpDocumentor\Reflection\DocBlock\Tags\Version' + ]; + + /** + * @var \ReflectionParameter[][] a lazy-loading cache containing parameters for each tagHandler that has been used. + */ + private $tagHandlerParameterCache = []; + + /** + * @var FqsenResolver + */ + private $fqsenResolver; + + /** + * @var mixed[] an array representing a simple Service Locator where we can store parameters and + * services that can be inserted into the Factory Methods of Tag Handlers. + */ + private $serviceLocator = []; + + /** + * Initialize this tag factory with the means to resolve an FQSEN and optionally a list of tag handlers. + * + * If no tag handlers are provided than the default list in the {@see self::$tagHandlerMappings} property + * is used. + * + * @param FqsenResolver $fqsenResolver + * @param string[] $tagHandlers + * + * @see self::registerTagHandler() to add a new tag handler to the existing default list. + */ + public function __construct(FqsenResolver $fqsenResolver, array $tagHandlers = null) + { + $this->fqsenResolver = $fqsenResolver; + if ($tagHandlers !== null) { + $this->tagHandlerMappings = $tagHandlers; + } + + $this->addService($fqsenResolver, FqsenResolver::class); + } + + /** + * {@inheritDoc} + */ + public function create($tagLine, TypeContext $context = null) + { + if (! $context) { + $context = new TypeContext(''); + } + + list($tagName, $tagBody) = $this->extractTagParts($tagLine); + + if ($tagBody !== '' && $tagBody[0] === '[') { + throw new \InvalidArgumentException( + 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' + ); + } + + return $this->createTag($tagBody, $tagName, $context); + } + + /** + * {@inheritDoc} + */ + public function addParameter($name, $value) + { + $this->serviceLocator[$name] = $value; + } + + /** + * {@inheritDoc} + */ + public function addService($service, $alias = null) + { + $this->serviceLocator[$alias ?: get_class($service)] = $service; + } + + /** + * {@inheritDoc} + */ + public function registerTagHandler($tagName, $handler) + { + Assert::stringNotEmpty($tagName); + Assert::stringNotEmpty($handler); + Assert::classExists($handler); + Assert::implementsInterface($handler, StaticMethod::class); + + if (strpos($tagName, '\\') && $tagName[0] !== '\\') { + throw new \InvalidArgumentException( + 'A namespaced tag must have a leading backslash as it must be fully qualified' + ); + } + + $this->tagHandlerMappings[$tagName] = $handler; + } + + /** + * Extracts all components for a tag. + * + * @param string $tagLine + * + * @return string[] + */ + private function extractTagParts($tagLine) + { + $matches = array(); + if (! preg_match('/^@(' . self::REGEX_TAGNAME . ')(?:\s*([^\s].*)|$)/us', $tagLine, $matches)) { + throw new \InvalidArgumentException( + 'The tag "' . $tagLine . '" does not seem to be wellformed, please check it for errors' + ); + } + + if (count($matches) < 3) { + $matches[] = ''; + } + + return array_slice($matches, 1); + } + + /** + * Creates a new tag object with the given name and body or returns null if the tag name was recognized but the + * body was invalid. + * + * @param string $body + * @param string $name + * @param TypeContext $context + * + * @return Tag|null + */ + private function createTag($body, $name, TypeContext $context) + { + $handlerClassName = $this->findHandlerClassName($name, $context); + $arguments = $this->getArgumentsForParametersFromWiring( + $this->fetchParametersForHandlerFactoryMethod($handlerClassName), + $this->getServiceLocatorWithDynamicParameters($context, $name, $body) + ) + ; + + return call_user_func_array([$handlerClassName, 'create'], $arguments); + } + + /** + * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). + * + * @param string $tagName + * @param TypeContext $context + * + * @return string + */ + private function findHandlerClassName($tagName, TypeContext $context) + { + $handlerClassName = Generic::class; + if (isset($this->tagHandlerMappings[$tagName])) { + $handlerClassName = $this->tagHandlerMappings[$tagName]; + } elseif ($this->isAnnotation($tagName)) { + // TODO: Annotation support is planned for a later stage and as such is disabled for now + // $tagName = (string)$this->fqsenResolver->resolve($tagName, $context); + // if (isset($this->annotationMappings[$tagName])) { + // $handlerClassName = $this->annotationMappings[$tagName]; + // } + } + + return $handlerClassName; + } + + /** + * Retrieves the arguments that need to be passed to the Factory Method with the given Parameters. + * + * @param \ReflectionParameter[] $parameters + * @param mixed[] $locator + * + * @return mixed[] A series of values that can be passed to the Factory Method of the tag whose parameters + * is provided with this method. + */ + private function getArgumentsForParametersFromWiring($parameters, $locator) + { + $arguments = []; + foreach ($parameters as $index => $parameter) { + $typeHint = $parameter->getClass() ? $parameter->getClass()->getName() : null; + if (isset($locator[$typeHint])) { + $arguments[] = $locator[$typeHint]; + continue; + } + + $parameterName = $parameter->getName(); + if (isset($locator[$parameterName])) { + $arguments[] = $locator[$parameterName]; + continue; + } + + $arguments[] = null; + } + + return $arguments; + } + + /** + * Retrieves a series of ReflectionParameter objects for the static 'create' method of the given + * tag handler class name. + * + * @param string $handlerClassName + * + * @return \ReflectionParameter[] + */ + private function fetchParametersForHandlerFactoryMethod($handlerClassName) + { + if (! isset($this->tagHandlerParameterCache[$handlerClassName])) { + $methodReflection = new \ReflectionMethod($handlerClassName, 'create'); + $this->tagHandlerParameterCache[$handlerClassName] = $methodReflection->getParameters(); + } + + return $this->tagHandlerParameterCache[$handlerClassName]; + } + + /** + * Returns a copy of this class' Service Locator with added dynamic parameters, such as the tag's name, body and + * Context. + * + * @param TypeContext $context The Context (namespace and aliasses) that may be passed and is used to resolve FQSENs. + * @param string $tagName The name of the tag that may be passed onto the factory method of the Tag class. + * @param string $tagBody The body of the tag that may be passed onto the factory method of the Tag class. + * + * @return mixed[] + */ + private function getServiceLocatorWithDynamicParameters(TypeContext $context, $tagName, $tagBody) + { + $locator = array_merge( + $this->serviceLocator, + [ + 'name' => $tagName, + 'body' => $tagBody, + TypeContext::class => $context + ] + ); + + return $locator; + } + + /** + * Returns whether the given tag belongs to an annotation. + * + * @param string $tagContent + * + * @todo this method should be populated once we implement Annotation notation support. + * + * @return bool + */ + private function isAnnotation($tagContent) + { + // 1. Contains a namespace separator + // 2. Contains parenthesis + // 3. Is present in a list of known annotations (make the algorithm smart by first checking is the last part + // of the annotation class name matches the found tag name + + return false; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php new file mode 100644 index 0000000..e765367 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tag.php @@ -0,0 +1,26 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; + +interface Tag +{ + public function getName(); + + public static function create($body); + + public function render(Formatter $formatter = null); + + public function __toString(); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php new file mode 100644 index 0000000..3c1d113 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/TagFactory.php @@ -0,0 +1,93 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock; + +use phpDocumentor\Reflection\Types\Context as TypeContext; + +interface TagFactory +{ + /** + * Adds a parameter to the service locator that can be injected in a tag's factory method. + * + * When calling a tag's "create" method we always check the signature for dependencies to inject. One way is to + * typehint a parameter in the signature so that we can use that interface or class name to inject a dependency + * (see {@see addService()} for more information on that). + * + * Another way is to check the name of the argument against the names in the Service Locator. With this method + * you can add a variable that will be inserted when a tag's create method is not typehinted and has a matching + * name. + * + * Be aware that there are two reserved names: + * + * - name, representing the name of the tag. + * - body, representing the complete body of the tag. + * + * These parameters are injected at the last moment and will override any existing parameter with those names. + * + * @param string $name + * @param mixed $value + * + * @return void + */ + public function addParameter($name, $value); + + /** + * Registers a service with the Service Locator using the FQCN of the class or the alias, if provided. + * + * When calling a tag's "create" method we always check the signature for dependencies to inject. If a parameter + * has a typehint then the ServiceLocator is queried to see if a Service is registered for that typehint. + * + * Because interfaces are regularly used as type-hints this method provides an alias parameter; if the FQCN of the + * interface is passed as alias then every time that interface is requested the provided service will be returned. + * + * @param object $service + * @param string $alias + * + * @return void + */ + public function addService($service); + + /** + * Factory method responsible for instantiating the correct sub type. + * + * @param string $tagLine The text for this tag, including description. + * @param TypeContext $context + * + * @throws \InvalidArgumentException if an invalid tag line was presented. + * + * @return Tag A new tag object. + */ + public function create($tagLine, TypeContext $context = null); + + /** + * Registers a handler for tags. + * + * If you want to use your own tags then you can use this method to instruct the TagFactory to register the name + * of a tag with the FQCN of a 'Tag Handler'. The Tag handler should implement the {@see Tag} interface (and thus + * the create method). + * + * @param string $tagName Name of tag to register a handler for. When registering a namespaced tag, the full + * name, along with a prefixing slash MUST be provided. + * @param string $handler FQCN of handler. + * + * @throws \InvalidArgumentException if the tag name is not a string + * @throws \InvalidArgumentException if the tag name is namespaced (contains backslashes) but does not start with + * a backslash + * @throws \InvalidArgumentException if the handler is not a string + * @throws \InvalidArgumentException if the handler is not an existing class + * @throws \InvalidArgumentException if the handler does not implement the {@see Tag} interface + * + * @return void + */ + public function registerTagHandler($tagName, $handler); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php new file mode 100644 index 0000000..29d7f1d --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Author.php @@ -0,0 +1,100 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use Webmozart\Assert\Assert; + +/** + * Reflection class for an {@}author tag in a Docblock. + */ +final class Author extends BaseTag implements Factory\StaticMethod +{ + /** @var string register that this is the author tag. */ + protected $name = 'author'; + + /** @var string The name of the author */ + private $authorName = ''; + + /** @var string The email of the author */ + private $authorEmail = ''; + + /** + * Initializes this tag with the author name and e-mail. + * + * @param string $authorName + * @param string $authorEmail + */ + public function __construct($authorName, $authorEmail) + { + Assert::string($authorName); + Assert::string($authorEmail); + if ($authorEmail && !filter_var($authorEmail, FILTER_VALIDATE_EMAIL)) { + throw new \InvalidArgumentException('The author tag does not have a valid e-mail address'); + } + + $this->authorName = $authorName; + $this->authorEmail = $authorEmail; + } + + /** + * Gets the author's name. + * + * @return string The author's name. + */ + public function getAuthorName() + { + return $this->authorName; + } + + /** + * Returns the author's email. + * + * @return string The author's email. + */ + public function getEmail() + { + return $this->authorEmail; + } + + /** + * Returns this tag in string form. + * + * @return string + */ + public function __toString() + { + return $this->authorName . (strlen($this->authorEmail) ? ' <' . $this->authorEmail . '>' : ''); + } + + /** + * Attempts to create a new Author object based on †he tag body. + * + * @param string $body + * + * @return static + */ + public static function create($body) + { + Assert::string($body); + + $splitTagContent = preg_match('/^([^\<]*)(?:\<([^\>]*)\>)?$/u', $body, $matches); + if (!$splitTagContent) { + return null; + } + + $authorName = trim($matches[1]); + $email = isset($matches[2]) ? trim($matches[2]) : ''; + + return new static($authorName, $email); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php new file mode 100644 index 0000000..14bb717 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/BaseTag.php @@ -0,0 +1,52 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock; +use phpDocumentor\Reflection\DocBlock\Description; + +/** + * Parses a tag definition for a DocBlock. + */ +abstract class BaseTag implements DocBlock\Tag +{ + /** @var string Name of the tag */ + protected $name = ''; + + /** @var Description|null Description of the tag. */ + protected $description; + + /** + * Gets the name of this tag. + * + * @return string The name of this tag. + */ + public function getName() + { + return $this->name; + } + + public function getDescription() + { + return $this->description; + } + + public function render(Formatter $formatter = null) + { + if ($formatter === null) { + $formatter = new Formatter\PassthroughFormatter(); + } + + return $formatter->format($this); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php new file mode 100644 index 0000000..31b4f82 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Covers.php @@ -0,0 +1,84 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\FqsenResolver; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a @covers tag in a Docblock. + */ +final class Covers extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'covers'; + + /** @var Fqsen */ + private $refers = null; + + /** + * Initializes this tag. + * + * @param Fqsen $refers + * @param Description $description + */ + public function __construct(Fqsen $refers, Description $description = null) + { + $this->refers = $refers; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + DescriptionFactory $descriptionFactory = null, + FqsenResolver $resolver = null, + TypeContext $context = null + ) + { + Assert::string($body); + Assert::notEmpty($body); + + $parts = preg_split('/\s+/Su', $body, 2); + + return new static( + $resolver->resolve($parts[0], $context), + $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + ); + } + + /** + * Returns the structural element this tag refers to. + * + * @return Fqsen + */ + public function getReference() + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + * + * @return string + */ + public function __toString() + { + return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php new file mode 100644 index 0000000..7c1039f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Deprecated.php @@ -0,0 +1,97 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}deprecated tag in a Docblock. + */ +final class Deprecated extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'deprecated'; + + /** + * PCRE regular expression matching a version vector. + * Assumes the "x" modifier. + */ + const REGEX_VECTOR = '(?: + # Normal release vectors. + \d\S* + | + # VCS version vectors. Per PHPCS, they are expected to + # follow the form of the VCS name, followed by ":", followed + # by the version vector itself. + # By convention, popular VCSes like CVS, SVN and GIT use "$" + # around the actual version vector. + [^\s\:]+\:\s*\$[^\$]+\$ + )'; + + /** @var string The version vector. */ + private $version = ''; + + public function __construct($version = null, Description $description = null) + { + Assert::nullOrStringNotEmpty($version); + + $this->version = $version; + $this->description = $description; + } + + /** + * @return static + */ + public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) + { + Assert::nullOrString($body); + if (empty($body)) { + return new static(); + } + + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return new static( + null, + null !== $descriptionFactory ? $descriptionFactory->create($body, $context) : null + ); + } + + return new static( + $matches[1], + $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + ); + } + + /** + * Gets the version section of the tag. + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php new file mode 100644 index 0000000..b77a934 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Example.php @@ -0,0 +1,176 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\Tag; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}example tag in a Docblock. + */ +final class Example extends BaseTag +{ + /** + * @var string Path to a file to use as an example. May also be an absolute URI. + */ + private $filePath; + + /** + * @var bool Whether the file path component represents an URI. This determines how the file portion + * appears at {@link getContent()}. + */ + private $isURI = false; + + /** + * @var + */ + private $startingLine; + + /** + * @var + */ + private $lineCount; + + public function __construct($filePath, $isURI, $startingLine, $lineCount, $description) + { + Assert::notEmpty($filePath); + Assert::integer($startingLine); + Assert::greaterThanEq($startingLine, 0); + + $this->filePath = $filePath; + $this->startingLine = $startingLine; + $this->lineCount = $lineCount; + $this->name = 'example'; + if ($description !== null) { + $this->description = trim($description); + } + + $this->isURI = $isURI; + } + + /** + * {@inheritdoc} + */ + public function getContent() + { + if (null === $this->description) { + $filePath = '"' . $this->filePath . '"'; + if ($this->isURI) { + $filePath = $this->isUriRelative($this->filePath) + ? str_replace('%2F', '/', rawurlencode($this->filePath)) + :$this->filePath; + } + + return trim($filePath . ' ' . parent::getDescription()); + } + + return $this->description; + } + + /** + * {@inheritdoc} + */ + public static function create($body) + { + // File component: File path in quotes or File URI / Source information + if (! preg_match('/^(?:\"([^\"]+)\"|(\S+))(?:\s+(.*))?$/sux', $body, $matches)) { + return null; + } + + $filePath = null; + $fileUri = null; + if ('' !== $matches[1]) { + $filePath = $matches[1]; + } else { + $fileUri = $matches[2]; + } + + $startingLine = 1; + $lineCount = null; + $description = null; + + if (array_key_exists(3, $matches)) { + $description = $matches[3]; + + // Starting line / Number of lines / Description + if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) { + $startingLine = (int)$contentMatches[1]; + if (isset($contentMatches[2]) && $contentMatches[2] !== '') { + $lineCount = (int)$contentMatches[2]; + } + + if (array_key_exists(3, $contentMatches)) { + $description = $contentMatches[3]; + } + } + } + + return new static( + $filePath !== null?$filePath:$fileUri, + $fileUri !== null, + $startingLine, + $lineCount, + $description + ); + } + + /** + * Returns the file path. + * + * @return string Path to a file to use as an example. + * May also be an absolute URI. + */ + public function getFilePath() + { + return $this->filePath; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return $this->filePath . ($this->description ? ' ' . $this->description : ''); + } + + /** + * Returns true if the provided URI is relative or contains a complete scheme (and thus is absolute). + * + * @param string $uri + * + * @return bool + */ + private function isUriRelative($uri) + { + return false === strpos($uri, ':'); + } + + /** + * @return int + */ + public function getStartingLine() + { + return $this->startingLine; + } + + /** + * @return int + */ + public function getLineCount() + { + return $this->lineCount; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php new file mode 100644 index 0000000..98aea45 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/StaticMethod.php @@ -0,0 +1,18 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Factory; + +interface StaticMethod +{ + public static function create($body); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php new file mode 100644 index 0000000..b9ca0b8 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Factory/Strategy.php @@ -0,0 +1,18 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Factory; + +interface Strategy +{ + public function create($body); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php new file mode 100644 index 0000000..64b2c60 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter.php @@ -0,0 +1,27 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Tag; + +interface Formatter +{ + /** + * Formats a tag into a string representation according to a specific format, such as Markdown. + * + * @param Tag $tag + * + * @return string + */ + public function format(Tag $tag); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php new file mode 100644 index 0000000..ceb40cc --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/AlignFormatter.php @@ -0,0 +1,47 @@ + + * @copyright 2017 Mike van Riel + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter; + +use phpDocumentor\Reflection\DocBlock\Tag; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; + +class AlignFormatter implements Formatter +{ + /** @var int The maximum tag name length. */ + protected $maxLen = 0; + + /** + * Constructor. + * + * @param Tag[] $tags All tags that should later be aligned with the formatter. + */ + public function __construct(array $tags) + { + foreach ($tags as $tag) { + $this->maxLen = max($this->maxLen, strlen($tag->getName())); + } + } + + /** + * Formats the given tag to return a simple plain text version. + * + * @param Tag $tag + * + * @return string + */ + public function format(Tag $tag) + { + return '@' . $tag->getName() . str_repeat(' ', $this->maxLen - strlen($tag->getName()) + 1) . (string)$tag; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php new file mode 100644 index 0000000..4e2c576 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Formatter/PassthroughFormatter.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Formatter; + +use phpDocumentor\Reflection\DocBlock\Tag; +use phpDocumentor\Reflection\DocBlock\Tags\Formatter; + +class PassthroughFormatter implements Formatter +{ + /** + * Formats the given tag to return a simple plain text version. + * + * @param Tag $tag + * + * @return string + */ + public function format(Tag $tag) + { + return trim('@' . $tag->getName() . ' ' . (string)$tag); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php new file mode 100644 index 0000000..e4c53e0 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Generic.php @@ -0,0 +1,91 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\DocBlock\StandardTagFactory; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Parses a tag definition for a DocBlock. + */ +class Generic extends BaseTag implements Factory\StaticMethod +{ + /** + * Parses a tag and populates the member variables. + * + * @param string $name Name of the tag. + * @param Description $description The contents of the given tag. + */ + public function __construct($name, Description $description = null) + { + $this->validateTagName($name); + + $this->name = $name; + $this->description = $description; + } + + /** + * Creates a new tag that represents any unknown tag type. + * + * @param string $body + * @param string $name + * @param DescriptionFactory $descriptionFactory + * @param TypeContext $context + * + * @return static + */ + public static function create( + $body, + $name = '', + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::string($body); + Assert::stringNotEmpty($name); + Assert::notNull($descriptionFactory); + + $description = $descriptionFactory && $body ? $descriptionFactory->create($body, $context) : null; + + return new static($name, $description); + } + + /** + * Returns the tag as a serialized string + * + * @return string + */ + public function __toString() + { + return ($this->description ? $this->description->render() : ''); + } + + /** + * Validates if the tag name matches the expected format, otherwise throws an exception. + * + * @param string $name + * + * @return void + */ + private function validateTagName($name) + { + if (! preg_match('/^' . StandardTagFactory::REGEX_TAGNAME . '$/u', $name)) { + throw new \InvalidArgumentException( + 'The tag name "' . $name . '" is not wellformed. Tags may only consist of letters, underscores, ' + . 'hyphens and backslashes.' + ); + } + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php new file mode 100644 index 0000000..9c0e367 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Link.php @@ -0,0 +1,77 @@ + + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a @link tag in a Docblock. + */ +final class Link extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'link'; + + /** @var string */ + private $link = ''; + + /** + * Initializes a link to a URL. + * + * @param string $link + * @param Description $description + */ + public function __construct($link, Description $description = null) + { + Assert::string($link); + + $this->link = $link; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) + { + Assert::string($body); + Assert::notNull($descriptionFactory); + + $parts = preg_split('/\s+/Su', $body, 2); + $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; + + return new static($parts[0], $description); + } + + /** + * Gets the link + * + * @return string + */ + public function getLink() + { + return $this->link; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return $this->link . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php new file mode 100644 index 0000000..d3c1cd1 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Method.php @@ -0,0 +1,239 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\Types\Void_; +use Webmozart\Assert\Assert; + +/** + * Reflection class for an {@}method in a Docblock. + */ +final class Method extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'method'; + + /** @var string */ + private $methodName = ''; + + /** @var string[] */ + private $arguments = []; + + /** @var bool */ + private $isStatic = false; + + /** @var Type */ + private $returnType; + + public function __construct( + $methodName, + array $arguments = [], + Type $returnType = null, + $static = false, + Description $description = null + ) { + Assert::stringNotEmpty($methodName); + Assert::boolean($static); + + if ($returnType === null) { + $returnType = new Void_(); + } + + $this->methodName = $methodName; + $this->arguments = $this->filterArguments($arguments); + $this->returnType = $returnType; + $this->isStatic = $static; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([ $typeResolver, $descriptionFactory ]); + + // 1. none or more whitespace + // 2. optionally the keyword "static" followed by whitespace + // 3. optionally a word with underscores followed by whitespace : as + // type for the return value + // 4. then optionally a word with underscores followed by () and + // whitespace : as method name as used by phpDocumentor + // 5. then a word with underscores, followed by ( and any character + // until a ) and whitespace : as method name with signature + // 6. any remaining text : as description + if (!preg_match( + '/^ + # Static keyword + # Declares a static method ONLY if type is also present + (?: + (static) + \s+ + )? + # Return type + (?: + ( + (?:[\w\|_\\\\]*\$this[\w\|_\\\\]*) + | + (?: + (?:[\w\|_\\\\]+) + # array notation + (?:\[\])* + )* + ) + \s+ + )? + # Legacy method name (not captured) + (?: + [\w_]+\(\)\s+ + )? + # Method name + ([\w\|_\\\\]+) + # Arguments + (?: + \(([^\)]*)\) + )? + \s* + # Description + (.*) + $/sux', + $body, + $matches + )) { + return null; + } + + list(, $static, $returnType, $methodName, $arguments, $description) = $matches; + + $static = $static === 'static'; + + if ($returnType === '') { + $returnType = 'void'; + } + + $returnType = $typeResolver->resolve($returnType, $context); + $description = $descriptionFactory->create($description, $context); + + if (is_string($arguments) && strlen($arguments) > 0) { + $arguments = explode(',', $arguments); + foreach($arguments as &$argument) { + $argument = explode(' ', self::stripRestArg(trim($argument)), 2); + if ($argument[0][0] === '$') { + $argumentName = substr($argument[0], 1); + $argumentType = new Void_(); + } else { + $argumentType = $typeResolver->resolve($argument[0], $context); + $argumentName = ''; + if (isset($argument[1])) { + $argument[1] = self::stripRestArg($argument[1]); + $argumentName = substr($argument[1], 1); + } + } + + $argument = [ 'name' => $argumentName, 'type' => $argumentType]; + } + } else { + $arguments = []; + } + + return new static($methodName, $arguments, $returnType, $static, $description); + } + + /** + * Retrieves the method name. + * + * @return string + */ + public function getMethodName() + { + return $this->methodName; + } + + /** + * @return string[] + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Checks whether the method tag describes a static method or not. + * + * @return bool TRUE if the method declaration is for a static method, FALSE otherwise. + */ + public function isStatic() + { + return $this->isStatic; + } + + /** + * @return Type + */ + public function getReturnType() + { + return $this->returnType; + } + + public function __toString() + { + $arguments = []; + foreach ($this->arguments as $argument) { + $arguments[] = $argument['type'] . ' $' . $argument['name']; + } + + return trim(($this->isStatic() ? 'static ' : '') + . (string)$this->returnType . ' ' + . $this->methodName + . '(' . implode(', ', $arguments) . ')' + . ($this->description ? ' ' . $this->description->render() : '')); + } + + private function filterArguments($arguments) + { + foreach ($arguments as &$argument) { + if (is_string($argument)) { + $argument = [ 'name' => $argument ]; + } + if (! isset($argument['type'])) { + $argument['type'] = new Void_(); + } + $keys = array_keys($argument); + if ($keys !== [ 'name', 'type' ]) { + throw new \InvalidArgumentException( + 'Arguments can only have the "name" and "type" fields, found: ' . var_export($keys, true) + ); + } + } + + return $arguments; + } + + private static function stripRestArg($argument) + { + if (strpos($argument, '...') === 0) { + $argument = trim(substr($argument, 3)); + } + + return $argument; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php new file mode 100644 index 0000000..1a51dc0 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Param.php @@ -0,0 +1,141 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for the {@}param tag in a Docblock. + */ +final class Param extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'param'; + + /** @var Type */ + private $type; + + /** @var string */ + private $variableName = ''; + + /** @var bool determines whether this is a variadic argument */ + private $isVariadic = false; + + /** + * @param string $variableName + * @param Type $type + * @param bool $isVariadic + * @param Description $description + */ + public function __construct($variableName, Type $type = null, $isVariadic = false, Description $description = null) + { + Assert::string($variableName); + Assert::boolean($isVariadic); + + $this->variableName = $variableName; + $this->type = $type; + $this->isVariadic = $isVariadic; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + $isVariadic = false; + + // if the first item that is encountered is not a variable; it is a type + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { + $type = $typeResolver->resolve(array_shift($parts), $context); + array_shift($parts); + } + + // if the next item starts with a $ or ...$ it must be the variable name + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$' || substr($parts[0], 0, 4) === '...$')) { + $variableName = array_shift($parts); + array_shift($parts); + + if (substr($variableName, 0, 3) === '...') { + $isVariadic = true; + $variableName = substr($variableName, 3); + } + + if (substr($variableName, 0, 1) === '$') { + $variableName = substr($variableName, 1); + } + } + + $description = $descriptionFactory->create(implode('', $parts), $context); + + return new static($variableName, $type, $isVariadic, $description); + } + + /** + * Returns the variable's name. + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Returns the variable's type or null if unknown. + * + * @return Type|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns whether this tag is variadic. + * + * @return boolean + */ + public function isVariadic() + { + return $this->isVariadic; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return ($this->type ? $this->type . ' ' : '') + . ($this->isVariadic() ? '...' : '') + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php new file mode 100644 index 0000000..3c59713 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Property.php @@ -0,0 +1,118 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}property tag in a Docblock. + */ +class Property extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'property'; + + /** @var Type */ + private $type; + + /** @var string */ + protected $variableName = ''; + + /** + * @param string $variableName + * @param Type $type + * @param Description $description + */ + public function __construct($variableName, Type $type = null, Description $description = null) + { + Assert::string($variableName); + + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + + // if the first item that is encountered is not a variable; it is a type + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { + $type = $typeResolver->resolve(array_shift($parts), $context); + array_shift($parts); + } + + // if the next item starts with a $ or ...$ it must be the variable name + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$')) { + $variableName = array_shift($parts); + array_shift($parts); + + if (substr($variableName, 0, 1) === '$') { + $variableName = substr($variableName, 1); + } + } + + $description = $descriptionFactory->create(implode('', $parts), $context); + + return new static($variableName, $type, $description); + } + + /** + * Returns the variable's name. + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Returns the variable's type or null if unknown. + * + * @return Type|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return ($this->type ? $this->type . ' ' : '') + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php new file mode 100644 index 0000000..bf2b805 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyRead.php @@ -0,0 +1,118 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}property-read tag in a Docblock. + */ +class PropertyRead extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'property-read'; + + /** @var Type */ + private $type; + + /** @var string */ + protected $variableName = ''; + + /** + * @param string $variableName + * @param Type $type + * @param Description $description + */ + public function __construct($variableName, Type $type = null, Description $description = null) + { + Assert::string($variableName); + + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + + // if the first item that is encountered is not a variable; it is a type + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { + $type = $typeResolver->resolve(array_shift($parts), $context); + array_shift($parts); + } + + // if the next item starts with a $ or ...$ it must be the variable name + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$')) { + $variableName = array_shift($parts); + array_shift($parts); + + if (substr($variableName, 0, 1) === '$') { + $variableName = substr($variableName, 1); + } + } + + $description = $descriptionFactory->create(implode('', $parts), $context); + + return new static($variableName, $type, $description); + } + + /** + * Returns the variable's name. + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Returns the variable's type or null if unknown. + * + * @return Type|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return ($this->type ? $this->type . ' ' : '') + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php new file mode 100644 index 0000000..db37e0f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/PropertyWrite.php @@ -0,0 +1,118 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}property-write tag in a Docblock. + */ +class PropertyWrite extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'property-write'; + + /** @var Type */ + private $type; + + /** @var string */ + protected $variableName = ''; + + /** + * @param string $variableName + * @param Type $type + * @param Description $description + */ + public function __construct($variableName, Type $type = null, Description $description = null) + { + Assert::string($variableName); + + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + + // if the first item that is encountered is not a variable; it is a type + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { + $type = $typeResolver->resolve(array_shift($parts), $context); + array_shift($parts); + } + + // if the next item starts with a $ or ...$ it must be the variable name + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$')) { + $variableName = array_shift($parts); + array_shift($parts); + + if (substr($variableName, 0, 1) === '$') { + $variableName = substr($variableName, 1); + } + } + + $description = $descriptionFactory->create(implode('', $parts), $context); + + return new static($variableName, $type, $description); + } + + /** + * Returns the variable's name. + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Returns the variable's type or null if unknown. + * + * @return Type|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return ($this->type ? $this->type . ' ' : '') + . '$' . $this->variableName + . ($this->description ? ' ' . $this->description : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php new file mode 100644 index 0000000..dc7b8b6 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Fqsen.php @@ -0,0 +1,42 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; + +use phpDocumentor\Reflection\Fqsen as RealFqsen; + +/** + * Fqsen reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + */ +final class Fqsen implements Reference +{ + /** + * @var RealFqsen + */ + private $fqsen; + + /** + * Fqsen constructor. + */ + public function __construct(RealFqsen $fqsen) + { + $this->fqsen = $fqsen; + } + + /** + * @return string string representation of the referenced fqsen + */ + public function __toString() + { + return (string)$this->fqsen; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php new file mode 100644 index 0000000..5bf27d3 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Reference.php @@ -0,0 +1,21 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; + +/** + * Interface for references in {@see phpDocumentor\Reflection\DocBlock\Tags\See} + */ +interface Reference +{ + public function __toString(); +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php new file mode 100644 index 0000000..2671d5e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Reference/Url.php @@ -0,0 +1,40 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags\Reference; + +use Webmozart\Assert\Assert; + +/** + * Url reference used by {@see phpDocumentor\Reflection\DocBlock\Tags\See} + */ +final class Url implements Reference +{ + /** + * @var string + */ + private $uri; + + /** + * Url constructor. + */ + public function __construct($uri) + { + Assert::stringNotEmpty($uri); + $this->uri = $uri; + } + + public function __toString() + { + return $this->uri; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php new file mode 100644 index 0000000..09a5870 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Return_.php @@ -0,0 +1,73 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}return tag in a Docblock. + */ +final class Return_ extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'return'; + + /** @var Type */ + private $type; + + public function __construct(Type $type, Description $description = null) + { + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) + { + Assert::string($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/\s+/Su', $body, 2); + + $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); + $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + + return new static($type, $description); + } + + /** + * Returns the type section of the variable. + * + * @return Type + */ + public function getType() + { + return $this->type; + } + + public function __toString() + { + return $this->type . ' ' . $this->description; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php new file mode 100644 index 0000000..3774b49 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/See.php @@ -0,0 +1,89 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef; +use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference; +use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url; +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\FqsenResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\DocBlock\Description; +use Webmozart\Assert\Assert; + +/** + * Reflection class for an {@}see tag in a Docblock. + */ +class See extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'see'; + + /** @var Reference */ + protected $refers = null; + + /** + * Initializes this tag. + * + * @param Reference $refers + * @param Description $description + */ + public function __construct(Reference $refers, Description $description = null) + { + $this->refers = $refers; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + FqsenResolver $resolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::string($body); + Assert::allNotNull([$resolver, $descriptionFactory]); + + $parts = preg_split('/\s+/Su', $body, 2); + $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; + + // https://tools.ietf.org/html/rfc2396#section-3 + if (preg_match('/\w:\/\/\w/i', $parts[0])) { + return new static(new Url($parts[0]), $description); + } + + return new static(new FqsenRef($resolver->resolve($parts[0], $context)), $description); + } + + /** + * Returns the ref of this tag. + * + * @return Reference + */ + public function getReference() + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + * + * @return string + */ + public function __toString() + { + return $this->refers . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php new file mode 100644 index 0000000..3d002ed --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Since.php @@ -0,0 +1,94 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}since tag in a Docblock. + */ +final class Since extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'since'; + + /** + * PCRE regular expression matching a version vector. + * Assumes the "x" modifier. + */ + const REGEX_VECTOR = '(?: + # Normal release vectors. + \d\S* + | + # VCS version vectors. Per PHPCS, they are expected to + # follow the form of the VCS name, followed by ":", followed + # by the version vector itself. + # By convention, popular VCSes like CVS, SVN and GIT use "$" + # around the actual version vector. + [^\s\:]+\:\s*\$[^\$]+\$ + )'; + + /** @var string The version vector. */ + private $version = ''; + + public function __construct($version = null, Description $description = null) + { + Assert::nullOrStringNotEmpty($version); + + $this->version = $version; + $this->description = $description; + } + + /** + * @return static + */ + public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) + { + Assert::nullOrString($body); + if (empty($body)) { + return new static(); + } + + $matches = []; + if (! preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return null; + } + + return new static( + $matches[1], + $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + ); + } + + /** + * Gets the version section of the tag. + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php new file mode 100644 index 0000000..b0646b9 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Source.php @@ -0,0 +1,96 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}source tag in a Docblock. + */ +final class Source extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'source'; + + /** @var int The starting line, relative to the structural element's location. */ + private $startingLine = 1; + + /** @var int|null The number of lines, relative to the starting line. NULL means "to the end". */ + private $lineCount = null; + + public function __construct($startingLine, $lineCount = null, Description $description = null) + { + Assert::integerish($startingLine); + Assert::nullOrIntegerish($lineCount); + + $this->startingLine = (int)$startingLine; + $this->lineCount = $lineCount !== null ? (int)$lineCount : null; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) + { + Assert::stringNotEmpty($body); + Assert::notNull($descriptionFactory); + + $startingLine = 1; + $lineCount = null; + $description = null; + + // Starting line / Number of lines / Description + if (preg_match('/^([1-9]\d*)\s*(?:((?1))\s+)?(.*)$/sux', $body, $matches)) { + $startingLine = (int)$matches[1]; + if (isset($matches[2]) && $matches[2] !== '') { + $lineCount = (int)$matches[2]; + } + $description = $matches[3]; + } + + return new static($startingLine, $lineCount, $descriptionFactory->create($description, $context)); + } + + /** + * Gets the starting line. + * + * @return int The starting line, relative to the structural element's + * location. + */ + public function getStartingLine() + { + return $this->startingLine; + } + + /** + * Returns the number of lines. + * + * @return int|null The number of lines, relative to the starting line. NULL + * means "to the end". + */ + public function getLineCount() + { + return $this->lineCount; + } + + public function __toString() + { + return $this->startingLine + . ($this->lineCount !== null ? ' ' . $this->lineCount : '') + . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php new file mode 100644 index 0000000..349e773 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Throws.php @@ -0,0 +1,72 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}throws tag in a Docblock. + */ +final class Throws extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'throws'; + + /** @var Type */ + private $type; + + public function __construct(Type $type, Description $description = null) + { + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::string($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/\s+/Su', $body, 2); + + $type = $typeResolver->resolve(isset($parts[0]) ? $parts[0] : '', $context); + $description = $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context); + + return new static($type, $description); + } + + /** + * Returns the type section of the variable. + * + * @return Type + */ + public function getType() + { + return $this->type; + } + + public function __toString() + { + return $this->type . ' ' . $this->description; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php new file mode 100644 index 0000000..00dc3e3 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Uses.php @@ -0,0 +1,83 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\FqsenResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}uses tag in a Docblock. + */ +final class Uses extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'uses'; + + /** @var Fqsen */ + protected $refers = null; + + /** + * Initializes this tag. + * + * @param Fqsen $refers + * @param Description $description + */ + public function __construct(Fqsen $refers, Description $description = null) + { + $this->refers = $refers; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + FqsenResolver $resolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::string($body); + Assert::allNotNull([$resolver, $descriptionFactory]); + + $parts = preg_split('/\s+/Su', $body, 2); + + return new static( + $resolver->resolve($parts[0], $context), + $descriptionFactory->create(isset($parts[1]) ? $parts[1] : '', $context) + ); + } + + /** + * Returns the structural element this tag refers to. + * + * @return Fqsen + */ + public function getReference() + { + return $this->refers; + } + + /** + * Returns a string representation of this tag. + * + * @return string + */ + public function __toString() + { + return $this->refers . ' ' . $this->description->render(); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php new file mode 100644 index 0000000..f431a86 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Var_.php @@ -0,0 +1,118 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\Type; +use phpDocumentor\Reflection\TypeResolver; +use phpDocumentor\Reflection\Types\Context as TypeContext; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}var tag in a Docblock. + */ +class Var_ extends BaseTag implements Factory\StaticMethod +{ + /** @var string */ + protected $name = 'var'; + + /** @var Type */ + private $type; + + /** @var string */ + protected $variableName = ''; + + /** + * @param string $variableName + * @param Type $type + * @param Description $description + */ + public function __construct($variableName, Type $type = null, Description $description = null) + { + Assert::string($variableName); + + $this->variableName = $variableName; + $this->type = $type; + $this->description = $description; + } + + /** + * {@inheritdoc} + */ + public static function create( + $body, + TypeResolver $typeResolver = null, + DescriptionFactory $descriptionFactory = null, + TypeContext $context = null + ) { + Assert::stringNotEmpty($body); + Assert::allNotNull([$typeResolver, $descriptionFactory]); + + $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); + $type = null; + $variableName = ''; + + // if the first item that is encountered is not a variable; it is a type + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { + $type = $typeResolver->resolve(array_shift($parts), $context); + array_shift($parts); + } + + // if the next item starts with a $ or ...$ it must be the variable name + if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] == '$')) { + $variableName = array_shift($parts); + array_shift($parts); + + if (substr($variableName, 0, 1) === '$') { + $variableName = substr($variableName, 1); + } + } + + $description = $descriptionFactory->create(implode('', $parts), $context); + + return new static($variableName, $type, $description); + } + + /** + * Returns the variable's name. + * + * @return string + */ + public function getVariableName() + { + return $this->variableName; + } + + /** + * Returns the variable's type or null if unknown. + * + * @return Type|null + */ + public function getType() + { + return $this->type; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return ($this->type ? $this->type.' ' : '') + .(empty($this->variableName) ? null : ('$'.$this->variableName)) + .($this->description ? ' '.$this->description : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php new file mode 100644 index 0000000..3e0e5be --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlock/Tags/Version.php @@ -0,0 +1,94 @@ + + * @copyright 2010-2011 Mike van Riel / Naenius (http://www.naenius.com) + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\DocBlock\Tags; + +use phpDocumentor\Reflection\Types\Context as TypeContext; +use phpDocumentor\Reflection\DocBlock\Description; +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use Webmozart\Assert\Assert; + +/** + * Reflection class for a {@}version tag in a Docblock. + */ +final class Version extends BaseTag implements Factory\StaticMethod +{ + protected $name = 'version'; + + /** + * PCRE regular expression matching a version vector. + * Assumes the "x" modifier. + */ + const REGEX_VECTOR = '(?: + # Normal release vectors. + \d\S* + | + # VCS version vectors. Per PHPCS, they are expected to + # follow the form of the VCS name, followed by ":", followed + # by the version vector itself. + # By convention, popular VCSes like CVS, SVN and GIT use "$" + # around the actual version vector. + [^\s\:]+\:\s*\$[^\$]+\$ + )'; + + /** @var string The version vector. */ + private $version = ''; + + public function __construct($version = null, Description $description = null) + { + Assert::nullOrStringNotEmpty($version); + + $this->version = $version; + $this->description = $description; + } + + /** + * @return static + */ + public static function create($body, DescriptionFactory $descriptionFactory = null, TypeContext $context = null) + { + Assert::nullOrString($body); + if (empty($body)) { + return new static(); + } + + $matches = []; + if (!preg_match('/^(' . self::REGEX_VECTOR . ')\s*(.+)?$/sux', $body, $matches)) { + return null; + } + + return new static( + $matches[1], + $descriptionFactory->create(isset($matches[2]) ? $matches[2] : '', $context) + ); + } + + /** + * Gets the version section of the tag. + * + * @return string + */ + public function getVersion() + { + return $this->version; + } + + /** + * Returns a string representation for this tag. + * + * @return string + */ + public function __toString() + { + return $this->version . ($this->description ? ' ' . $this->description->render() : ''); + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php new file mode 100644 index 0000000..9ec2455 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactory.php @@ -0,0 +1,277 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +use phpDocumentor\Reflection\DocBlock\DescriptionFactory; +use phpDocumentor\Reflection\DocBlock\StandardTagFactory; +use phpDocumentor\Reflection\DocBlock\Tag; +use phpDocumentor\Reflection\DocBlock\TagFactory; +use Webmozart\Assert\Assert; + +final class DocBlockFactory implements DocBlockFactoryInterface +{ + /** @var DocBlock\DescriptionFactory */ + private $descriptionFactory; + + /** @var DocBlock\TagFactory */ + private $tagFactory; + + /** + * Initializes this factory with the required subcontractors. + * + * @param DescriptionFactory $descriptionFactory + * @param TagFactory $tagFactory + */ + public function __construct(DescriptionFactory $descriptionFactory, TagFactory $tagFactory) + { + $this->descriptionFactory = $descriptionFactory; + $this->tagFactory = $tagFactory; + } + + /** + * Factory method for easy instantiation. + * + * @param string[] $additionalTags + * + * @return DocBlockFactory + */ + public static function createInstance(array $additionalTags = []) + { + $fqsenResolver = new FqsenResolver(); + $tagFactory = new StandardTagFactory($fqsenResolver); + $descriptionFactory = new DescriptionFactory($tagFactory); + + $tagFactory->addService($descriptionFactory); + $tagFactory->addService(new TypeResolver($fqsenResolver)); + + $docBlockFactory = new self($descriptionFactory, $tagFactory); + foreach ($additionalTags as $tagName => $tagHandler) { + $docBlockFactory->registerTagHandler($tagName, $tagHandler); + } + + return $docBlockFactory; + } + + /** + * @param object|string $docblock A string containing the DocBlock to parse or an object supporting the + * getDocComment method (such as a ReflectionClass object). + * @param Types\Context $context + * @param Location $location + * + * @return DocBlock + */ + public function create($docblock, Types\Context $context = null, Location $location = null) + { + if (is_object($docblock)) { + if (!method_exists($docblock, 'getDocComment')) { + $exceptionMessage = 'Invalid object passed; the given object must support the getDocComment method'; + throw new \InvalidArgumentException($exceptionMessage); + } + + $docblock = $docblock->getDocComment(); + } + + Assert::stringNotEmpty($docblock); + + if ($context === null) { + $context = new Types\Context(''); + } + + $parts = $this->splitDocBlock($this->stripDocComment($docblock)); + list($templateMarker, $summary, $description, $tags) = $parts; + + return new DocBlock( + $summary, + $description ? $this->descriptionFactory->create($description, $context) : null, + array_filter($this->parseTagBlock($tags, $context), function($tag) { + return $tag instanceof Tag; + }), + $context, + $location, + $templateMarker === '#@+', + $templateMarker === '#@-' + ); + } + + public function registerTagHandler($tagName, $handler) + { + $this->tagFactory->registerTagHandler($tagName, $handler); + } + + /** + * Strips the asterisks from the DocBlock comment. + * + * @param string $comment String containing the comment text. + * + * @return string + */ + private function stripDocComment($comment) + { + $comment = trim(preg_replace('#[ \t]*(?:\/\*\*|\*\/|\*)?[ \t]{0,1}(.*)?#u', '$1', $comment)); + + // reg ex above is not able to remove */ from a single line docblock + if (substr($comment, -2) == '*/') { + $comment = trim(substr($comment, 0, -2)); + } + + return str_replace(array("\r\n", "\r"), "\n", $comment); + } + + /** + * Splits the DocBlock into a template marker, summary, description and block of tags. + * + * @param string $comment Comment to split into the sub-parts. + * + * @author Richard van Velzen (@_richardJ) Special thanks to Richard for the regex responsible for the split. + * @author Mike van Riel for extending the regex with template marker support. + * + * @return string[] containing the template marker (if any), summary, description and a string containing the tags. + */ + private function splitDocBlock($comment) + { + // Performance improvement cheat: if the first character is an @ then only tags are in this DocBlock. This + // method does not split tags so we return this verbatim as the fourth result (tags). This saves us the + // performance impact of running a regular expression + if (strpos($comment, '@') === 0) { + return array('', '', '', $comment); + } + + // clears all extra horizontal whitespace from the line endings to prevent parsing issues + $comment = preg_replace('/\h*$/Sum', '', $comment); + + /* + * Splits the docblock into a template marker, summary, description and tags section. + * + * - The template marker is empty, #@+ or #@- if the DocBlock starts with either of those (a newline may + * occur after it and will be stripped). + * - The short description is started from the first character until a dot is encountered followed by a + * newline OR two consecutive newlines (horizontal whitespace is taken into account to consider spacing + * errors). This is optional. + * - The long description, any character until a new line is encountered followed by an @ and word + * characters (a tag). This is optional. + * - Tags; the remaining characters + * + * Big thanks to RichardJ for contributing this Regular Expression + */ + preg_match( + '/ + \A + # 1. Extract the template marker + (?:(\#\@\+|\#\@\-)\n?)? + + # 2. Extract the summary + (?: + (?! @\pL ) # The summary may not start with an @ + ( + [^\n.]+ + (?: + (?! \. \n | \n{2} ) # End summary upon a dot followed by newline or two newlines + [\n.] (?! [ \t]* @\pL ) # End summary when an @ is found as first character on a new line + [^\n.]+ # Include anything else + )* + \.? + )? + ) + + # 3. Extract the description + (?: + \s* # Some form of whitespace _must_ precede a description because a summary must be there + (?! @\pL ) # The description may not start with an @ + ( + [^\n]+ + (?: \n+ + (?! [ \t]* @\pL ) # End description when an @ is found as first character on a new line + [^\n]+ # Include anything else + )* + ) + )? + + # 4. Extract the tags (anything that follows) + (\s+ [\s\S]*)? # everything that follows + /ux', + $comment, + $matches + ); + array_shift($matches); + + while (count($matches) < 4) { + $matches[] = ''; + } + + return $matches; + } + + /** + * Creates the tag objects. + * + * @param string $tags Tag block to parse. + * @param Types\Context $context Context of the parsed Tag + * + * @return DocBlock\Tag[] + */ + private function parseTagBlock($tags, Types\Context $context) + { + $tags = $this->filterTagBlock($tags); + if (!$tags) { + return []; + } + + $result = $this->splitTagBlockIntoTagLines($tags); + foreach ($result as $key => $tagLine) { + $result[$key] = $this->tagFactory->create(trim($tagLine), $context); + } + + return $result; + } + + /** + * @param string $tags + * + * @return string[] + */ + private function splitTagBlockIntoTagLines($tags) + { + $result = array(); + foreach (explode("\n", $tags) as $tag_line) { + if (isset($tag_line[0]) && ($tag_line[0] === '@')) { + $result[] = $tag_line; + } else { + $result[count($result) - 1] .= "\n" . $tag_line; + } + } + + return $result; + } + + /** + * @param $tags + * @return string + */ + private function filterTagBlock($tags) + { + $tags = trim($tags); + if (!$tags) { + return null; + } + + if ('@' !== $tags[0]) { + // @codeCoverageIgnoreStart + // Can't simulate this; this only happens if there is an error with the parsing of the DocBlock that + // we didn't foresee. + throw new \LogicException('A tag block started with text instead of an at-sign(@): ' . $tags); + // @codeCoverageIgnoreEnd + } + + return $tags; + } +} diff --git a/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php new file mode 100644 index 0000000..b353342 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/reflection-docblock/src/DocBlockFactoryInterface.php @@ -0,0 +1,23 @@ + please note that if you want to pass partial class names that additional steps are necessary, see the + > chapter `Resolving partial classes and FQSENs` for more information. + +Where the FqsenResolver can resolve: + +- Constant expressions (i.e. `@see \MyNamespace\MY_CONSTANT`) +- Function expressions (i.e. `@see \MyNamespace\myFunction()`) +- Class expressions (i.e. `@see \MyNamespace\MyClass`) +- Interface expressions (i.e. `@see \MyNamespace\MyInterface`) +- Trait expressions (i.e. `@see \MyNamespace\MyTrait`) +- Class constant expressions (i.e. `@see \MyNamespace\MyClass::MY_CONSTANT`) +- Property expressions (i.e. `@see \MyNamespace\MyClass::$myProperty`) +- Method expressions (i.e. `@see \MyNamespace\MyClass::myMethod()`) + +## Resolving a type + +In order to resolve a type you will have to instantiate the class `\phpDocumentor\Reflection\TypeResolver` +and call its `resolve` method like this: + +```php +$typeResolver = new \phpDocumentor\Reflection\TypeResolver(); +$type = $typeResolver->resolve('string|integer'); +``` + +In this example you will receive a Value Object of class `\phpDocumentor\Reflection\Types\Compound` that has two +elements, one of type `\phpDocumentor\Reflection\Types\String_` and one of type +`\phpDocumentor\Reflection\Types\Integer`. + +The real power of this resolver is in its capability to expand partial class names into fully qualified class names; but +in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will inform the resolver +in which namespace the given expression occurs and which namespace aliases (or imports) apply. + +## Resolving an FQSEN + +A Fully Qualified Structural Element Name is a reference to another element in your code bases and can be resolved using +the `\phpDocumentor\Reflection\FqsenResolver` class' `resolve` method, like this: + +```php +$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); +$fqsen = $fqsenResolver->resolve('\phpDocumentor\Reflection\FqsenResolver::resolve()'); +``` + +In this example we resolve a Fully Qualified Structural Element Name (meaning that it includes the full namespace, class +name and element name) and receive a Value Object of type `\phpDocumentor\Reflection\Fqsen`. + +The real power of this resolver is in its capability to expand partial element names into Fully Qualified Structural +Element Names; but in order to do that we need an additional `\phpDocumentor\Reflection\Types\Context` class that will +inform the resolver in which namespace the given expression occurs and which namespace aliases (or imports) apply. + +## Resolving partial Classes and Structural Element Names + +Perhaps the best feature of this library is that it knows how to resolve partial class names into fully qualified class +names. + +For example, you have this file: + +```php +namespace My\Example; + +use phpDocumentor\Reflection\Types; + +class Classy +{ + /** + * @var Types\Context + * @see Classy::otherFunction() + */ + public function __construct($context) {} + + public function otherFunction(){} +} +``` + +Suppose that you would want to resolve (and expand) the type in the `@var` tag and the element name in the `@see` tag. +For the resolvers to know how to expand partial names you have to provide a bit of _Context_ for them by instantiating +a new class named `\phpDocumentor\Reflection\Types\Context` with the name of the namespace and the aliases that are in +play. + +### Creating a Context + +You can do this by manually creating a Context like this: + +```php +$context = new \phpDocumentor\Reflection\Types\Context( + '\My\Example', + [ 'Types' => '\phpDocumentor\Reflection\Types'] +); +``` + +Or by using the `\phpDocumentor\Reflection\Types\ContextFactory` to instantiate a new context based on a Reflector +object or by providing the namespace that you'd like to extract and the source code of the file in which the given +type expression occurs. + +```php +$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory(); +$context = $contextFactory->createFromReflector(new ReflectionMethod('\My\Example\Classy', '__construct')); +``` + +or + +```php +$contextFactory = new \phpDocumentor\Reflection\Types\ContextFactory(); +$context = $contextFactory->createForNamespace('\My\Example', file_get_contents('My/Example/Classy.php')); +``` + +### Using the Context + +After you have obtained a Context it is just a matter of passing it along with the `resolve` method of either Resolver +class as second argument and the Resolvers will take this into account when resolving partial names. + +To obtain the resolved class name for the `@var` tag in the example above you can do: + +```php +$typeResolver = new \phpDocumentor\Reflection\TypeResolver(); +$type = $typeResolver->resolve('Types\Context', $context); +``` + +When you do this you will receive an object of class `\phpDocumentor\Reflection\Types\Object_` for which you can call +the `getFqsen` method to receive a Value Object that represents the complete FQSEN. So that would be +`phpDocumentor\Reflection\Types\Context`. + +> Why is the FQSEN wrapped in another object `Object_`? +> +> The resolve method of the TypeResolver only returns object with the interface `Type` and the FQSEN is a common +> type that does not represent a Type. Also: in some cases a type can represent an "Untyped Object", meaning that it +> is an object (signified by the `object` keyword) but does not refer to a specific element using an FQSEN. + +Another example is on how to resolve the FQSEN of a method as can be seen with the `@see` tag in the example above. To +resolve that you can do the following: + +```php +$fqsenResolver = new \phpDocumentor\Reflection\FqsenResolver(); +$type = $fqsenResolver->resolve('Classy::otherFunction()', $context); +``` + +Because Classy is a Class in the current namespace its FQSEN will have the `My\Example` namespace and by calling the +`resolve` method of the FQSEN Resolver you will receive an `Fqsen` object that refers to +`\My\Example\Classy::otherFunction()`. diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/composer.json b/www/multitube/vendor/phpdocumentor/type-resolver/composer.json new file mode 100644 index 0000000..82ead15 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/composer.json @@ -0,0 +1,27 @@ +{ + "name": "phpdocumentor/type-resolver", + "type": "library", + "license": "MIT", + "authors": [ + {"name": "Mike van Riel", "email": "me@mikevanriel.com"} + ], + "require": { + "php": "^5.5 || ^7.0", + "phpdocumentor/reflection-common": "^1.0" + }, + "autoload": { + "psr-4": {"phpDocumentor\\Reflection\\": ["src/"]} + }, + "autoload-dev": { + "psr-4": {"phpDocumentor\\Reflection\\": ["tests/unit"]} + }, + "require-dev": { + "phpunit/phpunit": "^5.2||^4.8.24", + "mockery/mockery": "^0.9.4" + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php new file mode 100644 index 0000000..9aa6ba3 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/FqsenResolver.php @@ -0,0 +1,77 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +use phpDocumentor\Reflection\Types\Context; + +class FqsenResolver +{ + /** @var string Definition of the NAMESPACE operator in PHP */ + const OPERATOR_NAMESPACE = '\\'; + + public function resolve($fqsen, Context $context = null) + { + if ($context === null) { + $context = new Context(''); + } + + if ($this->isFqsen($fqsen)) { + return new Fqsen($fqsen); + } + + return $this->resolvePartialStructuralElementName($fqsen, $context); + } + + /** + * Tests whether the given type is a Fully Qualified Structural Element Name. + * + * @param string $type + * + * @return bool + */ + private function isFqsen($type) + { + return strpos($type, self::OPERATOR_NAMESPACE) === 0; + } + + /** + * Resolves a partial Structural Element Name (i.e. `Reflection\DocBlock`) to its FQSEN representation + * (i.e. `\phpDocumentor\Reflection\DocBlock`) based on the Namespace and aliases mentioned in the Context. + * + * @param string $type + * @param Context $context + * + * @return Fqsen + * @throws \InvalidArgumentException when type is not a valid FQSEN. + */ + private function resolvePartialStructuralElementName($type, Context $context) + { + $typeParts = explode(self::OPERATOR_NAMESPACE, $type, 2); + + $namespaceAliases = $context->getNamespaceAliases(); + + // if the first segment is not an alias; prepend namespace name and return + if (!isset($namespaceAliases[$typeParts[0]])) { + $namespace = $context->getNamespace(); + if ('' !== $namespace) { + $namespace .= self::OPERATOR_NAMESPACE; + } + + return new Fqsen(self::OPERATOR_NAMESPACE . $namespace . $type); + } + + $typeParts[0] = $namespaceAliases[$typeParts[0]]; + + return new Fqsen(self::OPERATOR_NAMESPACE . implode(self::OPERATOR_NAMESPACE, $typeParts)); + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Type.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Type.php new file mode 100644 index 0000000..33ca559 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Type.php @@ -0,0 +1,18 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +interface Type +{ + public function __toString(); +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/TypeResolver.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/TypeResolver.php new file mode 100644 index 0000000..08b2a5f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/TypeResolver.php @@ -0,0 +1,298 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection; + +use phpDocumentor\Reflection\Types\Array_; +use phpDocumentor\Reflection\Types\Compound; +use phpDocumentor\Reflection\Types\Context; +use phpDocumentor\Reflection\Types\Iterable_; +use phpDocumentor\Reflection\Types\Nullable; +use phpDocumentor\Reflection\Types\Object_; + +final class TypeResolver +{ + /** @var string Definition of the ARRAY operator for types */ + const OPERATOR_ARRAY = '[]'; + + /** @var string Definition of the NAMESPACE operator in PHP */ + const OPERATOR_NAMESPACE = '\\'; + + /** @var string[] List of recognized keywords and unto which Value Object they map */ + private $keywords = array( + 'string' => Types\String_::class, + 'int' => Types\Integer::class, + 'integer' => Types\Integer::class, + 'bool' => Types\Boolean::class, + 'boolean' => Types\Boolean::class, + 'float' => Types\Float_::class, + 'double' => Types\Float_::class, + 'object' => Object_::class, + 'mixed' => Types\Mixed_::class, + 'array' => Array_::class, + 'resource' => Types\Resource_::class, + 'void' => Types\Void_::class, + 'null' => Types\Null_::class, + 'scalar' => Types\Scalar::class, + 'callback' => Types\Callable_::class, + 'callable' => Types\Callable_::class, + 'false' => Types\Boolean::class, + 'true' => Types\Boolean::class, + 'self' => Types\Self_::class, + '$this' => Types\This::class, + 'static' => Types\Static_::class, + 'parent' => Types\Parent_::class, + 'iterable' => Iterable_::class, + ); + + /** @var FqsenResolver */ + private $fqsenResolver; + + /** + * Initializes this TypeResolver with the means to create and resolve Fqsen objects. + * + * @param FqsenResolver $fqsenResolver + */ + public function __construct(FqsenResolver $fqsenResolver = null) + { + $this->fqsenResolver = $fqsenResolver ?: new FqsenResolver(); + } + + /** + * Analyzes the given type and returns the FQCN variant. + * + * When a type is provided this method checks whether it is not a keyword or + * Fully Qualified Class Name. If so it will use the given namespace and + * aliases to expand the type to a FQCN representation. + * + * This method only works as expected if the namespace and aliases are set; + * no dynamic reflection is being performed here. + * + * @param string $type The relative or absolute type. + * @param Context $context + * + * @uses Context::getNamespace() to determine with what to prefix the type name. + * @uses Context::getNamespaceAliases() to check whether the first part of the relative type name should not be + * replaced with another namespace. + * + * @return Type|null + */ + public function resolve($type, Context $context = null) + { + if (!is_string($type)) { + throw new \InvalidArgumentException( + 'Attempted to resolve type but it appeared not to be a string, received: ' . var_export($type, true) + ); + } + + $type = trim($type); + if (!$type) { + throw new \InvalidArgumentException('Attempted to resolve "' . $type . '" but it appears to be empty'); + } + + if ($context === null) { + $context = new Context(''); + } + + switch (true) { + case $this->isNullableType($type): + return $this->resolveNullableType($type, $context); + case $this->isKeyword($type): + return $this->resolveKeyword($type); + case ($this->isCompoundType($type)): + return $this->resolveCompoundType($type, $context); + case $this->isTypedArray($type): + return $this->resolveTypedArray($type, $context); + case $this->isFqsen($type): + return $this->resolveTypedObject($type); + case $this->isPartialStructuralElementName($type): + return $this->resolveTypedObject($type, $context); + // @codeCoverageIgnoreStart + default: + // I haven't got the foggiest how the logic would come here but added this as a defense. + throw new \RuntimeException( + 'Unable to resolve type "' . $type . '", there is no known method to resolve it' + ); + } + // @codeCoverageIgnoreEnd + } + + /** + * Adds a keyword to the list of Keywords and associates it with a specific Value Object. + * + * @param string $keyword + * @param string $typeClassName + * + * @return void + */ + public function addKeyword($keyword, $typeClassName) + { + if (!class_exists($typeClassName)) { + throw new \InvalidArgumentException( + 'The Value Object that needs to be created with a keyword "' . $keyword . '" must be an existing class' + . ' but we could not find the class ' . $typeClassName + ); + } + + if (!in_array(Type::class, class_implements($typeClassName))) { + throw new \InvalidArgumentException( + 'The class "' . $typeClassName . '" must implement the interface "phpDocumentor\Reflection\Type"' + ); + } + + $this->keywords[$keyword] = $typeClassName; + } + + /** + * Detects whether the given type represents an array. + * + * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. + * + * @return bool + */ + private function isTypedArray($type) + { + return substr($type, -2) === self::OPERATOR_ARRAY; + } + + /** + * Detects whether the given type represents a PHPDoc keyword. + * + * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. + * + * @return bool + */ + private function isKeyword($type) + { + return in_array(strtolower($type), array_keys($this->keywords), true); + } + + /** + * Detects whether the given type represents a relative structural element name. + * + * @param string $type A relative or absolute type as defined in the phpDocumentor documentation. + * + * @return bool + */ + private function isPartialStructuralElementName($type) + { + return ($type[0] !== self::OPERATOR_NAMESPACE) && !$this->isKeyword($type); + } + + /** + * Tests whether the given type is a Fully Qualified Structural Element Name. + * + * @param string $type + * + * @return bool + */ + private function isFqsen($type) + { + return strpos($type, self::OPERATOR_NAMESPACE) === 0; + } + + /** + * Tests whether the given type is a compound type (i.e. `string|int`). + * + * @param string $type + * + * @return bool + */ + private function isCompoundType($type) + { + return strpos($type, '|') !== false; + } + + /** + * Test whether the given type is a nullable type (i.e. `?string`) + * + * @param string $type + * + * @return bool + */ + private function isNullableType($type) + { + return $type[0] === '?'; + } + + /** + * Resolves the given typed array string (i.e. `string[]`) into an Array object with the right types set. + * + * @param string $type + * @param Context $context + * + * @return Array_ + */ + private function resolveTypedArray($type, Context $context) + { + return new Array_($this->resolve(substr($type, 0, -2), $context)); + } + + /** + * Resolves the given keyword (such as `string`) into a Type object representing that keyword. + * + * @param string $type + * + * @return Type + */ + private function resolveKeyword($type) + { + $className = $this->keywords[strtolower($type)]; + + return new $className(); + } + + /** + * Resolves the given FQSEN string into an FQSEN object. + * + * @param string $type + * @param Context|null $context + * + * @return Object_ + */ + private function resolveTypedObject($type, Context $context = null) + { + return new Object_($this->fqsenResolver->resolve($type, $context)); + } + + /** + * Resolves a compound type (i.e. `string|int`) into the appropriate Type objects or FQSEN. + * + * @param string $type + * @param Context $context + * + * @return Compound + */ + private function resolveCompoundType($type, Context $context) + { + $types = []; + + foreach (explode('|', $type) as $part) { + $types[] = $this->resolve($part, $context); + } + + return new Compound($types); + } + + /** + * Resolve nullable types (i.e. `?string`) into a Nullable type wrapper + * + * @param string $type + * @param Context $context + * + * @return Nullable + */ + private function resolveNullableType($type, Context $context) + { + return new Nullable($this->resolve(ltrim($type, '?'), $context)); + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Array_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Array_.php new file mode 100644 index 0000000..49b7c6e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Array_.php @@ -0,0 +1,86 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Represents an array type as described in the PSR-5, the PHPDoc Standard. + * + * An array can be represented in two forms: + * + * 1. Untyped (`array`), where the key and value type is unknown and hence classified as 'Mixed_'. + * 2. Types (`string[]`), where the value type is provided by preceding an opening and closing square bracket with a + * type name. + */ +final class Array_ implements Type +{ + /** @var Type */ + private $valueType; + + /** @var Type */ + private $keyType; + + /** + * Initializes this representation of an array with the given Type or Fqsen. + * + * @param Type $valueType + * @param Type $keyType + */ + public function __construct(Type $valueType = null, Type $keyType = null) + { + if ($keyType === null) { + $keyType = new Compound([ new String_(), new Integer() ]); + } + if ($valueType === null) { + $valueType = new Mixed_(); + } + + $this->valueType = $valueType; + $this->keyType = $keyType; + } + + /** + * Returns the type for the keys of this array. + * + * @return Type + */ + public function getKeyType() + { + return $this->keyType; + } + + /** + * Returns the value for the keys of this array. + * + * @return Type + */ + public function getValueType() + { + return $this->valueType; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + if ($this->valueType instanceof Mixed_) { + return 'array'; + } + + return $this->valueType . '[]'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php new file mode 100644 index 0000000..f82b19e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Boolean.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a Boolean type. + */ +final class Boolean implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'bool'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php new file mode 100644 index 0000000..68ebfbd --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Callable_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a Callable type. + */ +final class Callable_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'callable'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Compound.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Compound.php new file mode 100644 index 0000000..be986c3 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Compound.php @@ -0,0 +1,93 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use ArrayIterator; +use IteratorAggregate; +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a Compound Type. + * + * A Compound Type is not so much a special keyword or object reference but is a series of Types that are separated + * using an OR operator (`|`). This combination of types signifies that whatever is associated with this compound type + * may contain a value with any of the given types. + */ +final class Compound implements Type, IteratorAggregate +{ + /** @var Type[] */ + private $types; + + /** + * Initializes a compound type (i.e. `string|int`) and tests if the provided types all implement the Type interface. + * + * @param Type[] $types + * @throws \InvalidArgumentException when types are not all instance of Type + */ + public function __construct(array $types) + { + foreach ($types as $type) { + if (!$type instanceof Type) { + throw new \InvalidArgumentException('A compound type can only have other types as elements'); + } + } + + $this->types = $types; + } + + /** + * Returns the type at the given index. + * + * @param integer $index + * + * @return Type|null + */ + public function get($index) + { + if (!$this->has($index)) { + return null; + } + + return $this->types[$index]; + } + + /** + * Tests if this compound type has a type with the given index. + * + * @param integer $index + * + * @return bool + */ + public function has($index) + { + return isset($this->types[$index]); + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return implode('|', $this->types); + } + + /** + * {@inheritdoc} + */ + public function getIterator() + { + return new ArrayIterator($this->types); + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Context.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Context.php new file mode 100644 index 0000000..4e9ce5a --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Context.php @@ -0,0 +1,84 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +/** + * Provides information about the Context in which the DocBlock occurs that receives this context. + * + * A DocBlock does not know of its own accord in which namespace it occurs and which namespace aliases are applicable + * for the block of code in which it is in. This information is however necessary to resolve Class names in tags since + * you can provide a short form or make use of namespace aliases. + * + * The phpDocumentor Reflection component knows how to create this class but if you use the DocBlock parser from your + * own application it is possible to generate a Context class using the ContextFactory; this will analyze the file in + * which an associated class resides for its namespace and imports. + * + * @see ContextFactory::createFromClassReflector() + * @see ContextFactory::createForNamespace() + */ +final class Context +{ + /** @var string The current namespace. */ + private $namespace; + + /** @var array List of namespace aliases => Fully Qualified Namespace. */ + private $namespaceAliases; + + /** + * Initializes the new context and normalizes all passed namespaces to be in Qualified Namespace Name (QNN) + * format (without a preceding `\`). + * + * @param string $namespace The namespace where this DocBlock resides in. + * @param array $namespaceAliases List of namespace aliases => Fully Qualified Namespace. + */ + public function __construct($namespace, array $namespaceAliases = []) + { + $this->namespace = ('global' !== $namespace && 'default' !== $namespace) + ? trim((string)$namespace, '\\') + : ''; + + foreach ($namespaceAliases as $alias => $fqnn) { + if ($fqnn[0] === '\\') { + $fqnn = substr($fqnn, 1); + } + if ($fqnn[strlen($fqnn) - 1] === '\\') { + $fqnn = substr($fqnn, 0, -1); + } + + $namespaceAliases[$alias] = $fqnn; + } + + $this->namespaceAliases = $namespaceAliases; + } + + /** + * Returns the Qualified Namespace Name (thus without `\` in front) where the associated element is in. + * + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * Returns a list of Qualified Namespace Names (thus without `\` in front) that are imported, the keys represent + * the alias for the imported Namespace. + * + * @return string[] + */ + public function getNamespaceAliases() + { + return $this->namespaceAliases; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php new file mode 100644 index 0000000..30936a3 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/ContextFactory.php @@ -0,0 +1,210 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +/** + * Convenience class to create a Context for DocBlocks when not using the Reflection Component of phpDocumentor. + * + * For a DocBlock to be able to resolve types that use partial namespace names or rely on namespace imports we need to + * provide a bit of context so that the DocBlock can read that and based on it decide how to resolve the types to + * Fully Qualified names. + * + * @see Context for more information. + */ +final class ContextFactory +{ + /** The literal used at the end of a use statement. */ + const T_LITERAL_END_OF_USE = ';'; + + /** The literal used between sets of use statements */ + const T_LITERAL_USE_SEPARATOR = ','; + + /** + * Build a Context given a Class Reflection. + * + * @param \Reflector $reflector + * + * @see Context for more information on Contexts. + * + * @return Context + */ + public function createFromReflector(\Reflector $reflector) + { + if (method_exists($reflector, 'getDeclaringClass')) { + $reflector = $reflector->getDeclaringClass(); + } + + $fileName = $reflector->getFileName(); + $namespace = $reflector->getNamespaceName(); + + if (file_exists($fileName)) { + return $this->createForNamespace($namespace, file_get_contents($fileName)); + } + + return new Context($namespace, []); + } + + /** + * Build a Context for a namespace in the provided file contents. + * + * @param string $namespace It does not matter if a `\` precedes the namespace name, this method first normalizes. + * @param string $fileContents the file's contents to retrieve the aliases from with the given namespace. + * + * @see Context for more information on Contexts. + * + * @return Context + */ + public function createForNamespace($namespace, $fileContents) + { + $namespace = trim($namespace, '\\'); + $useStatements = []; + $currentNamespace = ''; + $tokens = new \ArrayIterator(token_get_all($fileContents)); + + while ($tokens->valid()) { + switch ($tokens->current()[0]) { + case T_NAMESPACE: + $currentNamespace = $this->parseNamespace($tokens); + break; + case T_CLASS: + // Fast-forward the iterator through the class so that any + // T_USE tokens found within are skipped - these are not + // valid namespace use statements so should be ignored. + $braceLevel = 0; + $firstBraceFound = false; + while ($tokens->valid() && ($braceLevel > 0 || !$firstBraceFound)) { + if ($tokens->current() === '{' + || $tokens->current()[0] === T_CURLY_OPEN + || $tokens->current()[0] === T_DOLLAR_OPEN_CURLY_BRACES) { + if (!$firstBraceFound) { + $firstBraceFound = true; + } + $braceLevel++; + } + + if ($tokens->current() === '}') { + $braceLevel--; + } + $tokens->next(); + } + break; + case T_USE: + if ($currentNamespace === $namespace) { + $useStatements = array_merge($useStatements, $this->parseUseStatement($tokens)); + } + break; + } + $tokens->next(); + } + + return new Context($namespace, $useStatements); + } + + /** + * Deduce the name from tokens when we are at the T_NAMESPACE token. + * + * @param \ArrayIterator $tokens + * + * @return string + */ + private function parseNamespace(\ArrayIterator $tokens) + { + // skip to the first string or namespace separator + $this->skipToNextStringOrNamespaceSeparator($tokens); + + $name = ''; + while ($tokens->valid() && ($tokens->current()[0] === T_STRING || $tokens->current()[0] === T_NS_SEPARATOR) + ) { + $name .= $tokens->current()[1]; + $tokens->next(); + } + + return $name; + } + + /** + * Deduce the names of all imports when we are at the T_USE token. + * + * @param \ArrayIterator $tokens + * + * @return string[] + */ + private function parseUseStatement(\ArrayIterator $tokens) + { + $uses = []; + $continue = true; + + while ($continue) { + $this->skipToNextStringOrNamespaceSeparator($tokens); + + list($alias, $fqnn) = $this->extractUseStatement($tokens); + $uses[$alias] = $fqnn; + if ($tokens->current()[0] === self::T_LITERAL_END_OF_USE) { + $continue = false; + } + } + + return $uses; + } + + /** + * Fast-forwards the iterator as longs as we don't encounter a T_STRING or T_NS_SEPARATOR token. + * + * @param \ArrayIterator $tokens + * + * @return void + */ + private function skipToNextStringOrNamespaceSeparator(\ArrayIterator $tokens) + { + while ($tokens->valid() && ($tokens->current()[0] !== T_STRING) && ($tokens->current()[0] !== T_NS_SEPARATOR)) { + $tokens->next(); + } + } + + /** + * Deduce the namespace name and alias of an import when we are at the T_USE token or have not reached the end of + * a USE statement yet. + * + * @param \ArrayIterator $tokens + * + * @return string + */ + private function extractUseStatement(\ArrayIterator $tokens) + { + $result = ['']; + while ($tokens->valid() + && ($tokens->current()[0] !== self::T_LITERAL_USE_SEPARATOR) + && ($tokens->current()[0] !== self::T_LITERAL_END_OF_USE) + ) { + if ($tokens->current()[0] === T_AS) { + $result[] = ''; + } + if ($tokens->current()[0] === T_STRING || $tokens->current()[0] === T_NS_SEPARATOR) { + $result[count($result) - 1] .= $tokens->current()[1]; + } + $tokens->next(); + } + + if (count($result) == 1) { + $backslashPos = strrpos($result[0], '\\'); + + if (false !== $backslashPos) { + $result[] = substr($result[0], $backslashPos + 1); + } else { + $result[] = $result[0]; + } + } + + return array_reverse($result); + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Float_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Float_.php new file mode 100644 index 0000000..e58d896 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Float_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a Float. + */ +final class Float_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'float'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Integer.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Integer.php new file mode 100644 index 0000000..be4555e --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Integer.php @@ -0,0 +1,28 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +final class Integer implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'int'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php new file mode 100644 index 0000000..0cbf48f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Iterable_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing iterable type + */ +final class Iterable_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'iterable'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php new file mode 100644 index 0000000..c1c165f --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Mixed_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing an unknown, or mixed, type. + */ +final class Mixed_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'mixed'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Null_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Null_.php new file mode 100644 index 0000000..203b422 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Null_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a null value or type. + */ +final class Null_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'null'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php new file mode 100644 index 0000000..3c6d1b1 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Nullable.php @@ -0,0 +1,56 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing a nullable type. The real type is wrapped. + */ +final class Nullable implements Type +{ + /** + * @var Type + */ + private $realType; + + /** + * Initialises this nullable type using the real type embedded + * + * @param Type $realType + */ + public function __construct(Type $realType) + { + $this->realType = $realType; + } + + /** + * Provide access to the actual type directly, if needed. + * + * @return Type + */ + public function getActualType() + { + return $this->realType; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return '?' . $this->realType->__toString(); + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Object_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Object_.php new file mode 100644 index 0000000..389f7c7 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Object_.php @@ -0,0 +1,71 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Fqsen; +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing an object. + * + * An object can be either typed or untyped. When an object is typed it means that it has an identifier, the FQSEN, + * pointing to an element in PHP. Object types that are untyped do not refer to a specific class but represent objects + * in general. + */ +final class Object_ implements Type +{ + /** @var Fqsen|null */ + private $fqsen; + + /** + * Initializes this object with an optional FQSEN, if not provided this object is considered 'untyped'. + * + * @param Fqsen $fqsen + * @throws \InvalidArgumentException when provided $fqsen is not a valid type. + */ + public function __construct(Fqsen $fqsen = null) + { + if (strpos((string)$fqsen, '::') !== false || strpos((string)$fqsen, '()') !== false) { + throw new \InvalidArgumentException( + 'Object types can only refer to a class, interface or trait but a method, function, constant or ' + . 'property was received: ' . (string)$fqsen + ); + } + + $this->fqsen = $fqsen; + } + + /** + * Returns the FQSEN associated with this object. + * + * @return Fqsen|null + */ + public function getFqsen() + { + return $this->fqsen; + } + + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + if ($this->fqsen) { + return (string)$this->fqsen; + } + + return 'object'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php new file mode 100644 index 0000000..aabdbfb --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Parent_.php @@ -0,0 +1,33 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the 'parent' type. + * + * Parent, as a Type, represents the parent class of class in which the associated element was defined. + */ +final class Parent_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'parent'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php new file mode 100644 index 0000000..a1b613d --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Resource_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the 'resource' Type. + */ +final class Resource_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'resource'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php new file mode 100644 index 0000000..1e2a660 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Scalar.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the 'scalar' pseudo-type, which is either a string, integer, float or boolean. + */ +final class Scalar implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'scalar'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Self_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Self_.php new file mode 100644 index 0000000..1ba3fc5 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Self_.php @@ -0,0 +1,33 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the 'self' type. + * + * Self, as a Type, represents the class in which the associated element was defined. + */ +final class Self_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'self'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Static_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Static_.php new file mode 100644 index 0000000..9eb6729 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Static_.php @@ -0,0 +1,38 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the 'static' type. + * + * Self, as a Type, represents the class in which the associated element was called. This differs from self as self does + * not take inheritance into account but static means that the return type is always that of the class of the called + * element. + * + * See the documentation on late static binding in the PHP Documentation for more information on the difference between + * static and self. + */ +final class Static_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'static'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/String_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/String_.php new file mode 100644 index 0000000..8db5968 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/String_.php @@ -0,0 +1,31 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the type 'string'. + */ +final class String_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'string'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/This.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/This.php new file mode 100644 index 0000000..c098a93 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/This.php @@ -0,0 +1,34 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the '$this' pseudo-type. + * + * $this, as a Type, represents the instance of the class associated with the element as it was called. $this is + * commonly used when documenting fluent interfaces since it represents that the same object is returned. + */ +final class This implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return '$this'; + } +} diff --git a/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Void_.php b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Void_.php new file mode 100644 index 0000000..3d1be27 --- /dev/null +++ b/www/multitube/vendor/phpdocumentor/type-resolver/src/Types/Void_.php @@ -0,0 +1,34 @@ + + * @license http://www.opensource.org/licenses/mit-license.php MIT + * @link http://phpdoc.org + */ + +namespace phpDocumentor\Reflection\Types; + +use phpDocumentor\Reflection\Type; + +/** + * Value Object representing the pseudo-type 'void'. + * + * Void is generally only used when working with return types as it signifies that the method intentionally does not + * return any value. + */ +final class Void_ implements Type +{ + /** + * Returns a rendered output of the Type as it would be used in a DocBlock. + * + * @return string + */ + public function __toString() + { + return 'void'; + } +} diff --git a/www/multitube/vendor/pimple/pimple/.gitignore b/www/multitube/vendor/pimple/pimple/.gitignore new file mode 100644 index 0000000..a5c7ed6 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/.gitignore @@ -0,0 +1,4 @@ +phpunit.xml +.phpunit.result.cache +composer.lock +/vendor/ diff --git a/www/multitube/vendor/pimple/pimple/.php_cs.dist b/www/multitube/vendor/pimple/pimple/.php_cs.dist new file mode 100644 index 0000000..2787bb4 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/.php_cs.dist @@ -0,0 +1,20 @@ +setRules([ + '@Symfony' => true, + '@Symfony:risky' => true, + '@PHPUnit75Migration:risky' => true, + 'php_unit_dedicate_assert' => true, + 'array_syntax' => ['syntax' => 'short'], + 'php_unit_fqcn_annotation' => true, + 'no_unreachable_default_argument_value' => false, + 'braces' => ['allow_single_line_closure' => true], + 'heredoc_to_nowdoc' => false, + 'ordered_imports' => true, + 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], + 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'], + ]) + ->setRiskyAllowed(true) + ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__.'/src')) +; diff --git a/www/multitube/vendor/pimple/pimple/.travis.yml b/www/multitube/vendor/pimple/pimple/.travis.yml new file mode 100644 index 0000000..046ec30 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/.travis.yml @@ -0,0 +1,19 @@ +language: php + +env: + global: + - REPORT_EXIT_STATUS=1 + +php: + - 7.2 + - 7.3 + - 7.4 + - 8.0 + - nightly + +before_script: + - composer self-update + - COMPOSER_ROOT_VERSION=dev-master composer install + +script: + - ./vendor/bin/simple-phpunit diff --git a/www/multitube/vendor/pimple/pimple/CHANGELOG b/www/multitube/vendor/pimple/pimple/CHANGELOG new file mode 100644 index 0000000..08059e5 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/CHANGELOG @@ -0,0 +1,72 @@ +* 3.4.0 (2021-03-06) + + * Implement version 1.1 of PSR-11 + +* 3.3.1 (2020-11-24) + + * Add support for PHP 8 + +* 3.3.0 (2020-03-03) + + * Drop PHP extension + * Bump min PHP version to 7.2.5 + +* 3.2.3 (2018-01-21) + + * prefixed all function calls with \ for extra speed + +* 3.2.2 (2017-07-23) + + * reverted extending a protected closure throws an exception (deprecated it instead) + +* 3.2.1 (2017-07-17) + + * fixed PHP error + +* 3.2.0 (2017-07-17) + + * added a PSR-11 service locator + * added a PSR-11 wrapper + * added ServiceIterator + * fixed extending a protected closure (now throws InvalidServiceIdentifierException) + +* 3.1.0 (2017-07-03) + + * deprecated the C extension + * added support for PSR-11 exceptions + +* 3.0.2 (2015-09-11) + + * refactored the C extension + * minor non-significant changes + +* 3.0.1 (2015-07-30) + + * simplified some code + * fixed a segfault in the C extension + +* 3.0.0 (2014-07-24) + + * removed the Pimple class alias (use Pimple\Container instead) + +* 2.1.1 (2014-07-24) + + * fixed compiler warnings for the C extension + * fixed code when dealing with circular references + +* 2.1.0 (2014-06-24) + + * moved the Pimple to Pimple\Container (with a BC layer -- Pimple is now a + deprecated alias which will be removed in Pimple 3.0) + * added Pimple\ServiceProviderInterface (and Pimple::register()) + +* 2.0.0 (2014-02-10) + + * changed extend to automatically re-assign the extended service and keep it as shared or factory + (to keep BC, extend still returns the extended service) + * changed services to be shared by default (use factory() for factory + services) + +* 1.0.0 + + * initial version diff --git a/www/multitube/vendor/pimple/pimple/LICENSE b/www/multitube/vendor/pimple/pimple/LICENSE new file mode 100644 index 0000000..3e2a9e1 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2009-2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/pimple/pimple/README.rst b/www/multitube/vendor/pimple/pimple/README.rst new file mode 100644 index 0000000..7081839 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/README.rst @@ -0,0 +1,332 @@ +Pimple +====== + +.. caution:: + + Pimple is now closed for changes. No new features will be added and no + cosmetic changes will be accepted either. The only accepted changes are + compatibility with newer PHP versions and security issue fixes. + +.. caution:: + + This is the documentation for Pimple 3.x. If you are using Pimple 1.x, read + the `Pimple 1.x documentation`_. Reading the Pimple 1.x code is also a good + way to learn more about how to create a simple Dependency Injection + Container (recent versions of Pimple are more focused on performance). + +Pimple is a small Dependency Injection Container for PHP. + +Installation +------------ + +Before using Pimple in your project, add it to your ``composer.json`` file: + +.. code-block:: bash + + $ ./composer.phar require pimple/pimple "^3.0" + +Usage +----- + +Creating a container is a matter of creating a ``Container`` instance: + +.. code-block:: php + + use Pimple\Container; + + $container = new Container(); + +As many other dependency injection containers, Pimple manages two different +kind of data: **services** and **parameters**. + +Defining Services +~~~~~~~~~~~~~~~~~ + +A service is an object that does something as part of a larger system. Examples +of services: a database connection, a templating engine, or a mailer. Almost +any **global** object can be a service. + +Services are defined by **anonymous functions** that return an instance of an +object: + +.. code-block:: php + + // define some services + $container['session_storage'] = function ($c) { + return new SessionStorage('SESSION_ID'); + }; + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + +Notice that the anonymous function has access to the current container +instance, allowing references to other services or parameters. + +As objects are only created when you get them, the order of the definitions +does not matter. + +Using the defined services is also very easy: + +.. code-block:: php + + // get the session object + $session = $container['session']; + + // the above call is roughly equivalent to the following code: + // $storage = new SessionStorage('SESSION_ID'); + // $session = new Session($storage); + +Defining Factory Services +~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, each time you get a service, Pimple returns the **same instance** +of it. If you want a different instance to be returned for all calls, wrap your +anonymous function with the ``factory()`` method + +.. code-block:: php + + $container['session'] = $container->factory(function ($c) { + return new Session($c['session_storage']); + }); + +Now, each call to ``$container['session']`` returns a new instance of the +session. + +Defining Parameters +~~~~~~~~~~~~~~~~~~~ + +Defining a parameter allows to ease the configuration of your container from +the outside and to store global values: + +.. code-block:: php + + // define some parameters + $container['cookie_name'] = 'SESSION_ID'; + $container['session_storage_class'] = 'SessionStorage'; + +If you change the ``session_storage`` service definition like below: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + +You can now easily change the cookie name by overriding the +``cookie_name`` parameter instead of redefining the service +definition. + +Protecting Parameters +~~~~~~~~~~~~~~~~~~~~~ + +Because Pimple sees anonymous functions as service definitions, you need to +wrap anonymous functions with the ``protect()`` method to store them as +parameters: + +.. code-block:: php + + $container['random_func'] = $container->protect(function () { + return rand(); + }); + +Modifying Services after Definition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In some cases you may want to modify a service definition after it has been +defined. You can use the ``extend()`` method to define additional code to be +run on your service just after it is created: + +.. code-block:: php + + $container['session_storage'] = function ($c) { + return new $c['session_storage_class']($c['cookie_name']); + }; + + $container->extend('session_storage', function ($storage, $c) { + $storage->...(); + + return $storage; + }); + +The first argument is the name of the service to extend, the second a function +that gets access to the object instance and the container. + +Extending a Container +~~~~~~~~~~~~~~~~~~~~~ + +If you use the same libraries over and over, you might want to reuse some +services from one project to the next one; package your services into a +**provider** by implementing ``Pimple\ServiceProviderInterface``: + +.. code-block:: php + + use Pimple\Container; + + class FooProvider implements Pimple\ServiceProviderInterface + { + public function register(Container $pimple) + { + // register some services and parameters + // on $pimple + } + } + +Then, register the provider on a Container: + +.. code-block:: php + + $pimple->register(new FooProvider()); + +Fetching the Service Creation Function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you access an object, Pimple automatically calls the anonymous function +that you defined, which creates the service object for you. If you want to get +raw access to this function, you can use the ``raw()`` method: + +.. code-block:: php + + $container['session'] = function ($c) { + return new Session($c['session_storage']); + }; + + $sessionFunction = $container->raw('session'); + +PSR-11 compatibility +-------------------- + +For historical reasons, the ``Container`` class does not implement the PSR-11 +``ContainerInterface``. However, Pimple provides a helper class that will let +you decouple your code from the Pimple container class. + +The PSR-11 container class +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``Pimple\Psr11\Container`` class lets you access the content of an +underlying Pimple container using ``Psr\Container\ContainerInterface`` +methods: + +.. code-block:: php + + use Pimple\Container; + use Pimple\Psr11\Container as PsrContainer; + + $container = new Container(); + $container['service'] = function ($c) { + return new Service(); + }; + $psr11 = new PsrContainer($container); + + $controller = function (PsrContainer $container) { + $service = $container->get('service'); + }; + $controller($psr11); + +Using the PSR-11 ServiceLocator +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Sometimes, a service needs access to several other services without being sure +that all of them will actually be used. In those cases, you may want the +instantiation of the services to be lazy. + +The traditional solution is to inject the entire service container to get only +the services really needed. However, this is not recommended because it gives +services a too broad access to the rest of the application and it hides their +actual dependencies. + +The ``ServiceLocator`` is intended to solve this problem by giving access to a +set of predefined services while instantiating them only when actually needed. + +It also allows you to make your services available under a different name than +the one used to register them. For instance, you may want to use an object +that expects an instance of ``EventDispatcherInterface`` to be available under +the name ``event_dispatcher`` while your event dispatcher has been +registered under the name ``dispatcher``: + +.. code-block:: php + + use Monolog\Logger; + use Pimple\Psr11\ServiceLocator; + use Psr\Container\ContainerInterface; + use Symfony\Component\EventDispatcher\EventDispatcher; + + class MyService + { + /** + * "logger" must be an instance of Psr\Log\LoggerInterface + * "event_dispatcher" must be an instance of Symfony\Component\EventDispatcher\EventDispatcherInterface + */ + private $services; + + public function __construct(ContainerInterface $services) + { + $this->services = $services; + } + } + + $container['logger'] = function ($c) { + return new Monolog\Logger(); + }; + $container['dispatcher'] = function () { + return new EventDispatcher(); + }; + + $container['service'] = function ($c) { + $locator = new ServiceLocator($c, array('logger', 'event_dispatcher' => 'dispatcher')); + + return new MyService($locator); + }; + +Referencing a Collection of Services Lazily +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Passing a collection of services instances in an array may prove inefficient +if the class that consumes the collection only needs to iterate over it at a +later stage, when one of its method is called. It can also lead to problems +if there is a circular dependency between one of the services stored in the +collection and the class that consumes it. + +The ``ServiceIterator`` class helps you solve these issues. It receives a +list of service names during instantiation and will retrieve the services +when iterated over: + +.. code-block:: php + + use Pimple\Container; + use Pimple\ServiceIterator; + + class AuthorizationService + { + private $voters; + + public function __construct($voters) + { + $this->voters = $voters; + } + + public function canAccess($resource) + { + foreach ($this->voters as $voter) { + if (true === $voter->canAccess($resource)) { + return true; + } + } + + return false; + } + } + + $container = new Container(); + + $container['voter1'] = function ($c) { + return new SomeVoter(); + } + $container['voter2'] = function ($c) { + return new SomeOtherVoter($c['auth']); + } + $container['auth'] = function ($c) { + return new AuthorizationService(new ServiceIterator($c, array('voter1', 'voter2')); + } + +.. _Pimple 1.x documentation: https://github.com/silexphp/Pimple/tree/1.1 diff --git a/www/multitube/vendor/pimple/pimple/composer.json b/www/multitube/vendor/pimple/pimple/composer.json new file mode 100644 index 0000000..fd319eb --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/composer.json @@ -0,0 +1,29 @@ +{ + "name": "pimple/pimple", + "type": "library", + "description": "Pimple, a simple Dependency Injection Container", + "keywords": ["dependency injection", "container"], + "homepage": "https://pimple.symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "require": { + "php": ">=7.2.5", + "psr/container": "^1.1" + }, + "require-dev": { + "symfony/phpunit-bridge": "^5.0" + }, + "autoload": { + "psr-0": { "Pimple": "src/" } + }, + "extra": { + "branch-alias": { + "dev-master": "3.4.x-dev" + } + } +} diff --git a/www/multitube/vendor/pimple/pimple/phpunit.xml.dist b/www/multitube/vendor/pimple/pimple/phpunit.xml.dist new file mode 100644 index 0000000..8990202 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/phpunit.xml.dist @@ -0,0 +1,18 @@ + + + + + + ./src/Pimple/Tests + + + + + + + diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Container.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Container.php new file mode 100644 index 0000000..715de10 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Container.php @@ -0,0 +1,298 @@ +factories = new \SplObjectStorage(); + $this->protected = new \SplObjectStorage(); + + foreach ($values as $key => $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Sets a parameter or an object. + * + * Objects must be defined as Closures. + * + * Allowing any PHP callable leads to difficult to debug problems + * as function names (strings) are callable (creating a function with + * the same name as an existing parameter would break your container). + * + * @param string $id The unique identifier for the parameter or object + * @param mixed $value The value of the parameter or a closure to define an object + * + * @throws FrozenServiceException Prevent override of a frozen service + */ + public function offsetSet($id, $value) + { + if (isset($this->frozen[$id])) { + throw new FrozenServiceException($id); + } + + $this->values[$id] = $value; + $this->keys[$id] = true; + } + + /** + * Gets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or an object + * + * @throws UnknownIdentifierException If the identifier is not defined + */ + public function offsetGet($id) + { + if (!isset($this->keys[$id])) { + throw new UnknownIdentifierException($id); + } + + if ( + isset($this->raw[$id]) + || !\is_object($this->values[$id]) + || isset($this->protected[$this->values[$id]]) + || !\method_exists($this->values[$id], '__invoke') + ) { + return $this->values[$id]; + } + + if (isset($this->factories[$this->values[$id]])) { + return $this->values[$id]($this); + } + + $raw = $this->values[$id]; + $val = $this->values[$id] = $raw($this); + $this->raw[$id] = $raw; + + $this->frozen[$id] = true; + + return $val; + } + + /** + * Checks if a parameter or an object is set. + * + * @param string $id The unique identifier for the parameter or object + * + * @return bool + */ + public function offsetExists($id) + { + return isset($this->keys[$id]); + } + + /** + * Unsets a parameter or an object. + * + * @param string $id The unique identifier for the parameter or object + */ + public function offsetUnset($id) + { + if (isset($this->keys[$id])) { + if (\is_object($this->values[$id])) { + unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]); + } + + unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]); + } + } + + /** + * Marks a callable as being a factory service. + * + * @param callable $callable A service definition to be used as a factory + * + * @return callable The passed callable + * + * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object + */ + public function factory($callable) + { + if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { + throw new ExpectedInvokableException('Service definition is not a Closure or invokable object.'); + } + + $this->factories->attach($callable); + + return $callable; + } + + /** + * Protects a callable from being interpreted as a service. + * + * This is useful when you want to store a callable as a parameter. + * + * @param callable $callable A callable to protect from being evaluated + * + * @return callable The passed callable + * + * @throws ExpectedInvokableException Service definition has to be a closure or an invokable object + */ + public function protect($callable) + { + if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { + throw new ExpectedInvokableException('Callable is not a Closure or invokable object.'); + } + + $this->protected->attach($callable); + + return $callable; + } + + /** + * Gets a parameter or the closure defining an object. + * + * @param string $id The unique identifier for the parameter or object + * + * @return mixed The value of the parameter or the closure defining an object + * + * @throws UnknownIdentifierException If the identifier is not defined + */ + public function raw($id) + { + if (!isset($this->keys[$id])) { + throw new UnknownIdentifierException($id); + } + + if (isset($this->raw[$id])) { + return $this->raw[$id]; + } + + return $this->values[$id]; + } + + /** + * Extends an object definition. + * + * Useful when you want to extend an existing object definition, + * without necessarily loading that object. + * + * @param string $id The unique identifier for the object + * @param callable $callable A service definition to extend the original + * + * @return callable The wrapped callable + * + * @throws UnknownIdentifierException If the identifier is not defined + * @throws FrozenServiceException If the service is frozen + * @throws InvalidServiceIdentifierException If the identifier belongs to a parameter + * @throws ExpectedInvokableException If the extension callable is not a closure or an invokable object + */ + public function extend($id, $callable) + { + if (!isset($this->keys[$id])) { + throw new UnknownIdentifierException($id); + } + + if (isset($this->frozen[$id])) { + throw new FrozenServiceException($id); + } + + if (!\is_object($this->values[$id]) || !\method_exists($this->values[$id], '__invoke')) { + throw new InvalidServiceIdentifierException($id); + } + + if (isset($this->protected[$this->values[$id]])) { + @\trigger_error(\sprintf('How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "%s" should be protected?', $id), E_USER_DEPRECATED); + } + + if (!\is_object($callable) || !\method_exists($callable, '__invoke')) { + throw new ExpectedInvokableException('Extension service definition is not a Closure or invokable object.'); + } + + $factory = $this->values[$id]; + + $extended = function ($c) use ($callable, $factory) { + return $callable($factory($c), $c); + }; + + if (isset($this->factories[$factory])) { + $this->factories->detach($factory); + $this->factories->attach($extended); + } + + return $this[$id] = $extended; + } + + /** + * Returns all defined value names. + * + * @return array An array of value names + */ + public function keys() + { + return \array_keys($this->values); + } + + /** + * Registers a service provider. + * + * @param ServiceProviderInterface $provider A ServiceProviderInterface instance + * @param array $values An array of values that customizes the provider + * + * @return static + */ + public function register(ServiceProviderInterface $provider, array $values = []) + { + $provider->register($this); + + foreach ($values as $key => $value) { + $this[$key] = $value; + } + + return $this; + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php new file mode 100644 index 0000000..7228421 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/ExpectedInvokableException.php @@ -0,0 +1,38 @@ + + */ +class ExpectedInvokableException extends \InvalidArgumentException implements ContainerExceptionInterface +{ +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php new file mode 100644 index 0000000..e4d2f6d --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/FrozenServiceException.php @@ -0,0 +1,45 @@ + + */ +class FrozenServiceException extends \RuntimeException implements ContainerExceptionInterface +{ + /** + * @param string $id Identifier of the frozen service + */ + public function __construct($id) + { + parent::__construct(\sprintf('Cannot override frozen service "%s".', $id)); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php new file mode 100644 index 0000000..91e82f9 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/InvalidServiceIdentifierException.php @@ -0,0 +1,45 @@ + + */ +class InvalidServiceIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface +{ + /** + * @param string $id The invalid identifier + */ + public function __construct($id) + { + parent::__construct(\sprintf('Identifier "%s" does not contain an object definition.', $id)); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php new file mode 100644 index 0000000..fb6b626 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Exception/UnknownIdentifierException.php @@ -0,0 +1,45 @@ + + */ +class UnknownIdentifierException extends \InvalidArgumentException implements NotFoundExceptionInterface +{ + /** + * @param string $id The unknown identifier + */ + public function __construct($id) + { + parent::__construct(\sprintf('Identifier "%s" is not defined.', $id)); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/Container.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/Container.php new file mode 100644 index 0000000..e18592e --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/Container.php @@ -0,0 +1,55 @@ + + */ +final class Container implements ContainerInterface +{ + private $pimple; + + public function __construct(PimpleContainer $pimple) + { + $this->pimple = $pimple; + } + + public function get(string $id) + { + return $this->pimple[$id]; + } + + public function has(string $id): bool + { + return isset($this->pimple[$id]); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php new file mode 100644 index 0000000..c173d7c --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Psr11/ServiceLocator.php @@ -0,0 +1,75 @@ + + */ +class ServiceLocator implements ContainerInterface +{ + private $container; + private $aliases = []; + + /** + * @param PimpleContainer $container The Container instance used to locate services + * @param array $ids Array of service ids that can be located. String keys can be used to define aliases + */ + public function __construct(PimpleContainer $container, array $ids) + { + $this->container = $container; + + foreach ($ids as $key => $id) { + $this->aliases[\is_int($key) ? $id : $key] = $id; + } + } + + /** + * {@inheritdoc} + */ + public function get(string $id) + { + if (!isset($this->aliases[$id])) { + throw new UnknownIdentifierException($id); + } + + return $this->container[$this->aliases[$id]]; + } + + /** + * {@inheritdoc} + */ + public function has(string $id) + { + return isset($this->aliases[$id]) && isset($this->container[$this->aliases[$id]]); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceIterator.php b/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceIterator.php new file mode 100644 index 0000000..5cde518 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceIterator.php @@ -0,0 +1,69 @@ + + */ +final class ServiceIterator implements \Iterator +{ + private $container; + private $ids; + + public function __construct(Container $container, array $ids) + { + $this->container = $container; + $this->ids = $ids; + } + + public function rewind() + { + \reset($this->ids); + } + + public function current() + { + return $this->container[\current($this->ids)]; + } + + public function key() + { + return \current($this->ids); + } + + public function next() + { + \next($this->ids); + } + + public function valid() + { + return null !== \key($this->ids); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php b/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php new file mode 100644 index 0000000..c004594 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/ServiceProviderInterface.php @@ -0,0 +1,46 @@ +value = $value; + + return $service; + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php new file mode 100644 index 0000000..33cd4e5 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/NonInvokable.php @@ -0,0 +1,34 @@ +factory(function () { + return new Service(); + }); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php new file mode 100644 index 0000000..d71b184 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Fixtures/Service.php @@ -0,0 +1,35 @@ + + */ +class Service +{ + public $value; +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php new file mode 100644 index 0000000..097a7fd --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleServiceProviderInterfaceTest.php @@ -0,0 +1,77 @@ + + */ +class PimpleServiceProviderInterfaceTest extends TestCase +{ + public function testProvider() + { + $pimple = new Container(); + + $pimpleServiceProvider = new Fixtures\PimpleServiceProvider(); + $pimpleServiceProvider->register($pimple); + + $this->assertEquals('value', $pimple['param']); + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testProviderWithRegisterMethod() + { + $pimple = new Container(); + + $pimple->register(new Fixtures\PimpleServiceProvider(), [ + 'anotherParameter' => 'anotherValue', + ]); + + $this->assertEquals('value', $pimple['param']); + $this->assertEquals('anotherValue', $pimple['anotherParameter']); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + + $serviceOne = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['factory']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php new file mode 100644 index 0000000..ffa50a6 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/PimpleTest.php @@ -0,0 +1,610 @@ + + */ +class PimpleTest extends TestCase +{ + public function testWithString() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + + $this->assertEquals('value', $pimple['param']); + } + + public function testWithClosure() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['service']); + } + + public function testServicesShouldBeDifferent() + { + $pimple = new Container(); + $pimple['service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $serviceOne = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertNotSame($serviceOne, $serviceTwo); + } + + public function testShouldPassContainerAsParameter() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $pimple['container'] = function ($container) { + return $container; + }; + + $this->assertNotSame($pimple, $pimple['service']); + $this->assertSame($pimple, $pimple['container']); + } + + public function testIsset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + $pimple['null'] = null; + + $this->assertTrue(isset($pimple['param'])); + $this->assertTrue(isset($pimple['service'])); + $this->assertTrue(isset($pimple['null'])); + $this->assertFalse(isset($pimple['non_existent'])); + } + + public function testConstructorInjection() + { + $params = ['param' => 'value']; + $pimple = new Container($params); + + $this->assertSame($params['param'], $pimple['param']); + } + + public function testOffsetGetValidatesKeyIsPresent() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + echo $pimple['foo']; + } + + /** + * @group legacy + */ + public function testLegacyOffsetGetValidatesKeyIsPresent() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + echo $pimple['foo']; + } + + public function testOffsetGetHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple['foo']); + } + + public function testUnset() + { + $pimple = new Container(); + $pimple['param'] = 'value'; + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + + unset($pimple['param'], $pimple['service']); + $this->assertFalse(isset($pimple['param'])); + $this->assertFalse(isset($pimple['service'])); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testShare($service) + { + $pimple = new Container(); + $pimple['shared_service'] = $service; + + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + + $this->assertSame($serviceOne, $serviceTwo); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testProtect($service) + { + $pimple = new Container(); + $pimple['protected'] = $pimple->protect($service); + + $this->assertSame($service, $pimple['protected']); + } + + public function testGlobalFunctionNameAsParameterValue() + { + $pimple = new Container(); + $pimple['global_function'] = 'strlen'; + $this->assertSame('strlen', $pimple['global_function']); + } + + public function testRaw() + { + $pimple = new Container(); + $pimple['service'] = $definition = $pimple->factory(function () { + return 'foo'; + }); + $this->assertSame($definition, $pimple->raw('service')); + } + + public function testRawHonorsNullValues() + { + $pimple = new Container(); + $pimple['foo'] = null; + $this->assertNull($pimple->raw('foo')); + } + + public function testFluentRegister() + { + $pimple = new Container(); + $this->assertSame($pimple, $pimple->register($this->getMockBuilder('Pimple\ServiceProviderInterface')->getMock())); + } + + public function testRawValidatesKeyIsPresent() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + $pimple->raw('foo'); + } + + /** + * @group legacy + */ + public function testLegacyRawValidatesKeyIsPresent() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + $pimple->raw('foo'); + } + + /** + * @dataProvider serviceDefinitionProvider + */ + public function testExtend($service) + { + $pimple = new Container(); + $pimple['shared_service'] = function () { + return new Fixtures\Service(); + }; + $pimple['factory_service'] = $pimple->factory(function () { + return new Fixtures\Service(); + }); + + $pimple->extend('shared_service', $service); + $serviceOne = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['shared_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertSame($serviceOne, $serviceTwo); + $this->assertSame($serviceOne->value, $serviceTwo->value); + + $pimple->extend('factory_service', $service); + $serviceOne = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceOne); + $serviceTwo = $pimple['factory_service']; + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $serviceTwo); + $this->assertNotSame($serviceOne, $serviceTwo); + $this->assertNotSame($serviceOne->value, $serviceTwo->value); + } + + public function testExtendDoesNotLeakWithFactories() + { + if (\extension_loaded('pimple')) { + $this->markTestSkipped('Pimple extension does not support this test'); + } + $pimple = new Container(); + + $pimple['foo'] = $pimple->factory(function () { + return; + }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $pimple) { + return; + }); + unset($pimple['foo']); + + $p = new \ReflectionProperty($pimple, 'values'); + $p->setAccessible(true); + $this->assertEmpty($p->getValue($pimple)); + + $p = new \ReflectionProperty($pimple, 'factories'); + $p->setAccessible(true); + $this->assertCount(0, $p->getValue($pimple)); + } + + public function testExtendValidatesKeyIsPresent() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + $pimple->extend('foo', function () { + }); + } + + /** + * @group legacy + */ + public function testLegacyExtendValidatesKeyIsPresent() + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + $pimple->extend('foo', function () { + }); + } + + public function testKeys() + { + $pimple = new Container(); + $pimple['foo'] = 123; + $pimple['bar'] = 123; + + $this->assertEquals(['foo', 'bar'], $pimple->keys()); + } + + /** @test */ + public function settingAnInvokableObjectShouldTreatItAsFactory() + { + $pimple = new Container(); + $pimple['invokable'] = new Fixtures\Invokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\Service', $pimple['invokable']); + } + + /** @test */ + public function settingNonInvokableObjectShouldTreatItAsParameter() + { + $pimple = new Container(); + $pimple['non_invokable'] = new Fixtures\NonInvokable(); + + $this->assertInstanceOf('Pimple\Tests\Fixtures\NonInvokable', $pimple['non_invokable']); + } + + /** + * @dataProvider badServiceDefinitionProvider + */ + public function testFactoryFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); + $this->expectExceptionMessage('Service definition is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple->factory($service); + } + + /** + * @group legacy + * @dataProvider badServiceDefinitionProvider + */ + public function testLegacyFactoryFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Service definition is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple->factory($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + */ + public function testProtectFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); + $this->expectExceptionMessage('Callable is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple->protect($service); + } + + /** + * @group legacy + * @dataProvider badServiceDefinitionProvider + */ + public function testLegacyProtectFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Callable is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple->protect($service); + } + + /** + * @dataProvider badServiceDefinitionProvider + */ + public function testExtendFailsForKeysNotContainingServiceDefinitions($service) + { + $this->expectException(\Pimple\Exception\InvalidServiceIdentifierException::class); + $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.'); + + $pimple = new Container(); + $pimple['foo'] = $service; + $pimple->extend('foo', function () { + }); + } + + /** + * @group legacy + * @dataProvider badServiceDefinitionProvider + */ + public function testLegacyExtendFailsForKeysNotContainingServiceDefinitions($service) + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Identifier "foo" does not contain an object definition.'); + + $pimple = new Container(); + $pimple['foo'] = $service; + $pimple->extend('foo', function () { + }); + } + + /** + * @group legacy + * @expectedDeprecation How Pimple behaves when extending protected closures will be fixed in Pimple 4. Are you sure "foo" should be protected? + */ + public function testExtendingProtectedClosureDeprecation() + { + $pimple = new Container(); + $pimple['foo'] = $pimple->protect(function () { + return 'bar'; + }); + + $pimple->extend('foo', function ($value) { + return $value.'-baz'; + }); + + $this->assertSame('bar-baz', $pimple['foo']); + } + + /** + * @dataProvider badServiceDefinitionProvider + */ + public function testExtendFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\Pimple\Exception\ExpectedInvokableException::class); + $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple['foo'] = function () { + }; + $pimple->extend('foo', $service); + } + + /** + * @group legacy + * @dataProvider badServiceDefinitionProvider + */ + public function testLegacyExtendFailsForInvalidServiceDefinitions($service) + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Extension service definition is not a Closure or invokable object.'); + + $pimple = new Container(); + $pimple['foo'] = function () { + }; + $pimple->extend('foo', $service); + } + + public function testExtendFailsIfFrozenServiceIsNonInvokable() + { + $this->expectException(\Pimple\Exception\FrozenServiceException::class); + $this->expectExceptionMessage('Cannot override frozen service "foo".'); + + $pimple = new Container(); + $pimple['foo'] = function () { + return new Fixtures\NonInvokable(); + }; + $foo = $pimple['foo']; + + $pimple->extend('foo', function () { + }); + } + + public function testExtendFailsIfFrozenServiceIsInvokable() + { + $this->expectException(\Pimple\Exception\FrozenServiceException::class); + $this->expectExceptionMessage('Cannot override frozen service "foo".'); + + $pimple = new Container(); + $pimple['foo'] = function () { + return new Fixtures\Invokable(); + }; + $foo = $pimple['foo']; + + $pimple->extend('foo', function () { + }); + } + + /** + * Provider for invalid service definitions. + */ + public function badServiceDefinitionProvider() + { + return [ + [123], + [new Fixtures\NonInvokable()], + ]; + } + + /** + * Provider for service definitions. + */ + public function serviceDefinitionProvider() + { + return [ + [function ($value) { + $service = new Fixtures\Service(); + $service->value = $value; + + return $service; + }], + [new Fixtures\Invokable()], + ]; + } + + public function testDefiningNewServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['bar']); + } + + public function testOverridingServiceAfterFreeze() + { + $this->expectException(\Pimple\Exception\FrozenServiceException::class); + $this->expectExceptionMessage('Cannot override frozen service "foo".'); + + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['foo'] = function () { + return 'bar'; + }; + } + + /** + * @group legacy + */ + public function testLegacyOverridingServiceAfterFreeze() + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Cannot override frozen service "foo".'); + + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + $pimple['foo'] = function () { + return 'bar'; + }; + } + + public function testRemovingServiceAfterFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $foo = $pimple['foo']; + + unset($pimple['foo']); + $pimple['foo'] = function () { + return 'bar'; + }; + $this->assertSame('bar', $pimple['foo']); + } + + public function testExtendingService() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.bar"; + }); + $pimple['foo'] = $pimple->extend('foo', function ($foo, $app) { + return "$foo.baz"; + }); + $this->assertSame('foo.bar.baz', $pimple['foo']); + } + + public function testExtendingServiceAfterOtherServiceFreeze() + { + $pimple = new Container(); + $pimple['foo'] = function () { + return 'foo'; + }; + $pimple['bar'] = function () { + return 'bar'; + }; + $foo = $pimple['foo']; + + $pimple['bar'] = $pimple->extend('bar', function ($bar, $app) { + return "$bar.baz"; + }); + $this->assertSame('bar.baz', $pimple['bar']); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php new file mode 100644 index 0000000..d47b9c3 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ContainerTest.php @@ -0,0 +1,76 @@ +assertSame($pimple['service'], $psr->get('service')); + } + + public function testGetThrowsExceptionIfServiceIsNotFound() + { + $this->expectException(\Psr\Container\NotFoundExceptionInterface::class); + $this->expectExceptionMessage('Identifier "service" is not defined.'); + + $pimple = new Container(); + $psr = new PsrContainer($pimple); + + $psr->get('service'); + } + + public function testHasReturnsTrueIfServiceExists() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Service(); + }; + $psr = new PsrContainer($pimple); + + $this->assertTrue($psr->has('service')); + } + + public function testHasReturnsFalseIfServiceDoesNotExist() + { + $pimple = new Container(); + $psr = new PsrContainer($pimple); + + $this->assertFalse($psr->has('service')); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php new file mode 100644 index 0000000..bd2d335 --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/Psr11/ServiceLocatorTest.php @@ -0,0 +1,131 @@ + + */ +class ServiceLocatorTest extends TestCase +{ + public function testCanAccessServices() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['service']); + + $this->assertSame($pimple['service'], $locator->get('service')); + } + + public function testCanAccessAliasedServices() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['alias' => 'service']); + + $this->assertSame($pimple['service'], $locator->get('alias')); + } + + public function testCannotAccessAliasedServiceUsingRealIdentifier() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "service" is not defined.'); + + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['alias' => 'service']); + + $service = $locator->get('service'); + } + + public function testGetValidatesServiceCanBeLocated() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "foo" is not defined.'); + + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['alias' => 'service']); + + $service = $locator->get('foo'); + } + + public function testGetValidatesTargetServiceExists() + { + $this->expectException(\Pimple\Exception\UnknownIdentifierException::class); + $this->expectExceptionMessage('Identifier "invalid" is not defined.'); + + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['alias' => 'invalid']); + + $service = $locator->get('alias'); + } + + public function testHasValidatesServiceCanBeLocated() + { + $pimple = new Container(); + $pimple['service1'] = function () { + return new Fixtures\Service(); + }; + $pimple['service2'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['service1']); + + $this->assertTrue($locator->has('service1')); + $this->assertFalse($locator->has('service2')); + } + + public function testHasChecksIfTargetServiceExists() + { + $pimple = new Container(); + $pimple['service'] = function () { + return new Fixtures\Service(); + }; + $locator = new ServiceLocator($pimple, ['foo' => 'service', 'bar' => 'invalid']); + + $this->assertTrue($locator->has('foo')); + $this->assertFalse($locator->has('bar')); + } +} diff --git a/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php new file mode 100644 index 0000000..2bb935f --- /dev/null +++ b/www/multitube/vendor/pimple/pimple/src/Pimple/Tests/ServiceIteratorTest.php @@ -0,0 +1,52 @@ +assertSame(['service1' => $pimple['service1'], 'service2' => $pimple['service2']], iterator_to_array($iterator)); + } +} diff --git a/www/multitube/vendor/psr/container/.gitignore b/www/multitube/vendor/psr/container/.gitignore new file mode 100644 index 0000000..b2395aa --- /dev/null +++ b/www/multitube/vendor/psr/container/.gitignore @@ -0,0 +1,3 @@ +composer.lock +composer.phar +/vendor/ diff --git a/www/multitube/vendor/psr/container/LICENSE b/www/multitube/vendor/psr/container/LICENSE new file mode 100644 index 0000000..2877a48 --- /dev/null +++ b/www/multitube/vendor/psr/container/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013-2016 container-interop +Copyright (c) 2016 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/www/multitube/vendor/psr/container/README.md b/www/multitube/vendor/psr/container/README.md new file mode 100644 index 0000000..1b9d9e5 --- /dev/null +++ b/www/multitube/vendor/psr/container/README.md @@ -0,0 +1,13 @@ +Container interface +============== + +This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url]. + +Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container. + +The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist. + +[psr-url]: https://www.php-fig.org/psr/psr-11/ +[package-url]: https://packagist.org/packages/psr/container +[implementation-url]: https://packagist.org/providers/psr/container-implementation + diff --git a/www/multitube/vendor/psr/container/composer.json b/www/multitube/vendor/psr/container/composer.json new file mode 100644 index 0000000..3797a25 --- /dev/null +++ b/www/multitube/vendor/psr/container/composer.json @@ -0,0 +1,22 @@ +{ + "name": "psr/container", + "type": "library", + "description": "Common Container Interface (PHP FIG PSR-11)", + "keywords": ["psr", "psr-11", "container", "container-interop", "container-interface"], + "homepage": "https://github.com/php-fig/container", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "require": { + "php": ">=7.2.0" + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + } +} diff --git a/www/multitube/vendor/psr/container/src/ContainerExceptionInterface.php b/www/multitube/vendor/psr/container/src/ContainerExceptionInterface.php new file mode 100644 index 0000000..cf10b8b --- /dev/null +++ b/www/multitube/vendor/psr/container/src/ContainerExceptionInterface.php @@ -0,0 +1,10 @@ +=7.0.0", + "psr/http-message": "^1.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/www/multitube/vendor/psr/http-factory/src/RequestFactoryInterface.php b/www/multitube/vendor/psr/http-factory/src/RequestFactoryInterface.php new file mode 100644 index 0000000..cb39a08 --- /dev/null +++ b/www/multitube/vendor/psr/http-factory/src/RequestFactoryInterface.php @@ -0,0 +1,18 @@ +=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/www/multitube/vendor/psr/http-message/src/MessageInterface.php b/www/multitube/vendor/psr/http-message/src/MessageInterface.php new file mode 100644 index 0000000..dd46e5e --- /dev/null +++ b/www/multitube/vendor/psr/http-message/src/MessageInterface.php @@ -0,0 +1,187 @@ +getHeaders() as $name => $values) { + * echo $name . ": " . implode(", ", $values); + * } + * + * // Emit headers iteratively: + * foreach ($message->getHeaders() as $name => $values) { + * foreach ($values as $value) { + * header(sprintf('%s: %s', $name, $value), false); + * } + * } + * + * While header names are not case-sensitive, getHeaders() will preserve the + * exact case in which headers were originally specified. + * + * @return string[][] Returns an associative array of the message's headers. Each + * key MUST be a header name, and each value MUST be an array of strings + * for that header. + */ + public function getHeaders(); + + /** + * Checks if a header exists by the given case-insensitive name. + * + * @param string $name Case-insensitive header field name. + * @return bool Returns true if any header names match the given header + * name using a case-insensitive string comparison. Returns false if + * no matching header name is found in the message. + */ + public function hasHeader($name); + + /** + * Retrieves a message header value by the given case-insensitive name. + * + * This method returns an array of all the header values of the given + * case-insensitive header name. + * + * If the header does not appear in the message, this method MUST return an + * empty array. + * + * @param string $name Case-insensitive header field name. + * @return string[] An array of string values as provided for the given + * header. If the header does not appear in the message, this method MUST + * return an empty array. + */ + public function getHeader($name); + + /** + * Retrieves a comma-separated string of the values for a single header. + * + * This method returns all of the header values of the given + * case-insensitive header name as a string concatenated together using + * a comma. + * + * NOTE: Not all header values may be appropriately represented using + * comma concatenation. For such headers, use getHeader() instead + * and supply your own delimiter when concatenating. + * + * If the header does not appear in the message, this method MUST return + * an empty string. + * + * @param string $name Case-insensitive header field name. + * @return string A string of values as provided for the given header + * concatenated together using a comma. If the header does not appear in + * the message, this method MUST return an empty string. + */ + public function getHeaderLine($name); + + /** + * Return an instance with the provided value replacing the specified header. + * + * While header names are case-insensitive, the casing of the header will + * be preserved by this function, and returned from getHeaders(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new and/or updated header and value. + * + * @param string $name Case-insensitive header field name. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withHeader($name, $value); + + /** + * Return an instance with the specified header appended with the given value. + * + * Existing values for the specified header will be maintained. The new + * value(s) will be appended to the existing list. If the header did not + * exist previously, it will be added. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * new header and/or value. + * + * @param string $name Case-insensitive header field name to add. + * @param string|string[] $value Header value(s). + * @return static + * @throws \InvalidArgumentException for invalid header names or values. + */ + public function withAddedHeader($name, $value); + + /** + * Return an instance without the specified header. + * + * Header resolution MUST be done without case-sensitivity. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the named header. + * + * @param string $name Case-insensitive header field name to remove. + * @return static + */ + public function withoutHeader($name); + + /** + * Gets the body of the message. + * + * @return StreamInterface Returns the body as a stream. + */ + public function getBody(); + + /** + * Return an instance with the specified message body. + * + * The body MUST be a StreamInterface object. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return a new instance that has the + * new body stream. + * + * @param StreamInterface $body Body. + * @return static + * @throws \InvalidArgumentException When the body is not valid. + */ + public function withBody(StreamInterface $body); +} diff --git a/www/multitube/vendor/psr/http-message/src/RequestInterface.php b/www/multitube/vendor/psr/http-message/src/RequestInterface.php new file mode 100644 index 0000000..a96d4fd --- /dev/null +++ b/www/multitube/vendor/psr/http-message/src/RequestInterface.php @@ -0,0 +1,129 @@ +getQuery()` + * or from the `QUERY_STRING` server param. + * + * @return array + */ + public function getQueryParams(); + + /** + * Return an instance with the specified query string arguments. + * + * These values SHOULD remain immutable over the course of the incoming + * request. They MAY be injected during instantiation, such as from PHP's + * $_GET superglobal, or MAY be derived from some other value such as the + * URI. In cases where the arguments are parsed from the URI, the data + * MUST be compatible with what PHP's parse_str() would return for + * purposes of how duplicate query parameters are handled, and how nested + * sets are handled. + * + * Setting query string arguments MUST NOT change the URI stored by the + * request, nor the values in the server params. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated query string arguments. + * + * @param array $query Array of query string arguments, typically from + * $_GET. + * @return static + */ + public function withQueryParams(array $query); + + /** + * Retrieve normalized file upload data. + * + * This method returns upload metadata in a normalized tree, with each leaf + * an instance of Psr\Http\Message\UploadedFileInterface. + * + * These values MAY be prepared from $_FILES or the message body during + * instantiation, or MAY be injected via withUploadedFiles(). + * + * @return array An array tree of UploadedFileInterface instances; an empty + * array MUST be returned if no data is present. + */ + public function getUploadedFiles(); + + /** + * Create a new instance with the specified uploaded files. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param array $uploadedFiles An array tree of UploadedFileInterface instances. + * @return static + * @throws \InvalidArgumentException if an invalid structure is provided. + */ + public function withUploadedFiles(array $uploadedFiles); + + /** + * Retrieve any parameters provided in the request body. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, this method MUST + * return the contents of $_POST. + * + * Otherwise, this method may return any results of deserializing + * the request body content; as parsing returns structured content, the + * potential types MUST be arrays or objects only. A null value indicates + * the absence of body content. + * + * @return null|array|object The deserialized body parameters, if any. + * These will typically be an array or object. + */ + public function getParsedBody(); + + /** + * Return an instance with the specified body parameters. + * + * These MAY be injected during instantiation. + * + * If the request Content-Type is either application/x-www-form-urlencoded + * or multipart/form-data, and the request method is POST, use this method + * ONLY to inject the contents of $_POST. + * + * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of + * deserializing the request body content. Deserialization/parsing returns + * structured data, and, as such, this method ONLY accepts arrays or objects, + * or a null value if nothing was available to parse. + * + * As an example, if content negotiation determines that the request data + * is a JSON payload, this method could be used to create a request + * instance with the deserialized parameters. + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated body parameters. + * + * @param null|array|object $data The deserialized body data. This will + * typically be in an array or object. + * @return static + * @throws \InvalidArgumentException if an unsupported argument type is + * provided. + */ + public function withParsedBody($data); + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + * + * @return array Attributes derived from the request. + */ + public function getAttributes(); + + /** + * Retrieve a single derived request attribute. + * + * Retrieves a single derived request attribute as described in + * getAttributes(). If the attribute has not been previously set, returns + * the default value as provided. + * + * This method obviates the need for a hasAttribute() method, as it allows + * specifying a default value to return if the attribute is not found. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $default Default value to return if the attribute does not exist. + * @return mixed + */ + public function getAttribute($name, $default = null); + + /** + * Return an instance with the specified derived request attribute. + * + * This method allows setting a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that has the + * updated attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @param mixed $value The value of the attribute. + * @return static + */ + public function withAttribute($name, $value); + + /** + * Return an instance that removes the specified derived request attribute. + * + * This method allows removing a single derived request attribute as + * described in getAttributes(). + * + * This method MUST be implemented in such a way as to retain the + * immutability of the message, and MUST return an instance that removes + * the attribute. + * + * @see getAttributes() + * @param string $name The attribute name. + * @return static + */ + public function withoutAttribute($name); +} diff --git a/www/multitube/vendor/psr/http-message/src/StreamInterface.php b/www/multitube/vendor/psr/http-message/src/StreamInterface.php new file mode 100644 index 0000000..f68f391 --- /dev/null +++ b/www/multitube/vendor/psr/http-message/src/StreamInterface.php @@ -0,0 +1,158 @@ + + * [user-info@]host[:port] + * + * + * If the port component is not set or is the standard port for the current + * scheme, it SHOULD NOT be included. + * + * @see https://tools.ietf.org/html/rfc3986#section-3.2 + * @return string The URI authority, in "[user-info@]host[:port]" format. + */ + public function getAuthority(); + + /** + * Retrieve the user information component of the URI. + * + * If no user information is present, this method MUST return an empty + * string. + * + * If a user is present in the URI, this will return that value; + * additionally, if the password is also present, it will be appended to the + * user value, with a colon (":") separating the values. + * + * The trailing "@" character is not part of the user information and MUST + * NOT be added. + * + * @return string The URI user information, in "username[:password]" format. + */ + public function getUserInfo(); + + /** + * Retrieve the host component of the URI. + * + * If no host is present, this method MUST return an empty string. + * + * The value returned MUST be normalized to lowercase, per RFC 3986 + * Section 3.2.2. + * + * @see http://tools.ietf.org/html/rfc3986#section-3.2.2 + * @return string The URI host. + */ + public function getHost(); + + /** + * Retrieve the port component of the URI. + * + * If a port is present, and it is non-standard for the current scheme, + * this method MUST return it as an integer. If the port is the standard port + * used with the current scheme, this method SHOULD return null. + * + * If no port is present, and no scheme is present, this method MUST return + * a null value. + * + * If no port is present, but a scheme is present, this method MAY return + * the standard port for that scheme, but SHOULD return null. + * + * @return null|int The URI port. + */ + public function getPort(); + + /** + * Retrieve the path component of the URI. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * Normally, the empty path "" and absolute path "/" are considered equal as + * defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically + * do this normalization because in contexts with a trimmed base path, e.g. + * the front controller, this difference becomes significant. It's the task + * of the user to handle both "" and "/". + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.3. + * + * As an example, if the value should include a slash ("/") not intended as + * delimiter between path segments, that value MUST be passed in encoded + * form (e.g., "%2F") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.3 + * @return string The URI path. + */ + public function getPath(); + + /** + * Retrieve the query string of the URI. + * + * If no query string is present, this method MUST return an empty string. + * + * The leading "?" character is not part of the query and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.4. + * + * As an example, if a value in a key/value pair of the query string should + * include an ampersand ("&") not intended as a delimiter between values, + * that value MUST be passed in encoded form (e.g., "%26") to the instance. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.4 + * @return string The URI query string. + */ + public function getQuery(); + + /** + * Retrieve the fragment component of the URI. + * + * If no fragment is present, this method MUST return an empty string. + * + * The leading "#" character is not part of the fragment and MUST NOT be + * added. + * + * The value returned MUST be percent-encoded, but MUST NOT double-encode + * any characters. To determine what characters to encode, please refer to + * RFC 3986, Sections 2 and 3.5. + * + * @see https://tools.ietf.org/html/rfc3986#section-2 + * @see https://tools.ietf.org/html/rfc3986#section-3.5 + * @return string The URI fragment. + */ + public function getFragment(); + + /** + * Return an instance with the specified scheme. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified scheme. + * + * Implementations MUST support the schemes "http" and "https" case + * insensitively, and MAY accommodate other schemes if required. + * + * An empty scheme is equivalent to removing the scheme. + * + * @param string $scheme The scheme to use with the new instance. + * @return static A new instance with the specified scheme. + * @throws \InvalidArgumentException for invalid or unsupported schemes. + */ + public function withScheme($scheme); + + /** + * Return an instance with the specified user information. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified user information. + * + * Password is optional, but the user information MUST include the + * user; an empty string for the user is equivalent to removing user + * information. + * + * @param string $user The user name to use for authority. + * @param null|string $password The password associated with $user. + * @return static A new instance with the specified user information. + */ + public function withUserInfo($user, $password = null); + + /** + * Return an instance with the specified host. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified host. + * + * An empty host value is equivalent to removing the host. + * + * @param string $host The hostname to use with the new instance. + * @return static A new instance with the specified host. + * @throws \InvalidArgumentException for invalid hostnames. + */ + public function withHost($host); + + /** + * Return an instance with the specified port. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified port. + * + * Implementations MUST raise an exception for ports outside the + * established TCP and UDP port ranges. + * + * A null value provided for the port is equivalent to removing the port + * information. + * + * @param null|int $port The port to use with the new instance; a null value + * removes the port information. + * @return static A new instance with the specified port. + * @throws \InvalidArgumentException for invalid ports. + */ + public function withPort($port); + + /** + * Return an instance with the specified path. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified path. + * + * The path can either be empty or absolute (starting with a slash) or + * rootless (not starting with a slash). Implementations MUST support all + * three syntaxes. + * + * If the path is intended to be domain-relative rather than path relative then + * it must begin with a slash ("/"). Paths not starting with a slash ("/") + * are assumed to be relative to some base path known to the application or + * consumer. + * + * Users can provide both encoded and decoded path characters. + * Implementations ensure the correct encoding as outlined in getPath(). + * + * @param string $path The path to use with the new instance. + * @return static A new instance with the specified path. + * @throws \InvalidArgumentException for invalid paths. + */ + public function withPath($path); + + /** + * Return an instance with the specified query string. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified query string. + * + * Users can provide both encoded and decoded query characters. + * Implementations ensure the correct encoding as outlined in getQuery(). + * + * An empty query string value is equivalent to removing the query string. + * + * @param string $query The query string to use with the new instance. + * @return static A new instance with the specified query string. + * @throws \InvalidArgumentException for invalid query strings. + */ + public function withQuery($query); + + /** + * Return an instance with the specified URI fragment. + * + * This method MUST retain the state of the current instance, and return + * an instance that contains the specified URI fragment. + * + * Users can provide both encoded and decoded fragment characters. + * Implementations ensure the correct encoding as outlined in getFragment(). + * + * An empty fragment value is equivalent to removing the fragment. + * + * @param string $fragment The fragment to use with the new instance. + * @return static A new instance with the specified fragment. + */ + public function withFragment($fragment); + + /** + * Return the string representation as a URI reference. + * + * Depending on which components of the URI are present, the resulting + * string is either a full URI or relative reference according to RFC 3986, + * Section 4.1. The method concatenates the various components of the URI, + * using the appropriate delimiters: + * + * - If a scheme is present, it MUST be suffixed by ":". + * - If an authority is present, it MUST be prefixed by "//". + * - The path can be concatenated without delimiters. But there are two + * cases where the path has to be adjusted to make the URI reference + * valid as PHP does not allow to throw an exception in __toString(): + * - If the path is rootless and an authority is present, the path MUST + * be prefixed by "/". + * - If the path is starting with more than one "/" and no authority is + * present, the starting slashes MUST be reduced to one. + * - If a query is present, it MUST be prefixed by "?". + * - If a fragment is present, it MUST be prefixed by "#". + * + * @see http://tools.ietf.org/html/rfc3986#section-4.1 + * @return string + */ + public function __toString(); +} diff --git a/www/multitube/vendor/psr/log/LICENSE b/www/multitube/vendor/psr/log/LICENSE new file mode 100644 index 0000000..474c952 --- /dev/null +++ b/www/multitube/vendor/psr/log/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2012 PHP Framework Interoperability Group + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/psr/log/Psr/Log/AbstractLogger.php b/www/multitube/vendor/psr/log/Psr/Log/AbstractLogger.php new file mode 100644 index 0000000..90e721a --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/AbstractLogger.php @@ -0,0 +1,128 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } +} diff --git a/www/multitube/vendor/psr/log/Psr/Log/InvalidArgumentException.php b/www/multitube/vendor/psr/log/Psr/Log/InvalidArgumentException.php new file mode 100644 index 0000000..67f852d --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -0,0 +1,7 @@ +logger = $logger; + } +} diff --git a/www/multitube/vendor/psr/log/Psr/Log/LoggerInterface.php b/www/multitube/vendor/psr/log/Psr/Log/LoggerInterface.php new file mode 100644 index 0000000..2206cfd --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/LoggerInterface.php @@ -0,0 +1,125 @@ +log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + abstract public function log($level, $message, array $context = array()); +} diff --git a/www/multitube/vendor/psr/log/Psr/Log/NullLogger.php b/www/multitube/vendor/psr/log/Psr/Log/NullLogger.php new file mode 100644 index 0000000..c8f7293 --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/NullLogger.php @@ -0,0 +1,30 @@ +logger) { }` + * blocks. + */ +class NullLogger extends AbstractLogger +{ + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + * + * @throws \Psr\Log\InvalidArgumentException + */ + public function log($level, $message, array $context = array()) + { + // noop + } +} diff --git a/www/multitube/vendor/psr/log/Psr/Log/Test/DummyTest.php b/www/multitube/vendor/psr/log/Psr/Log/Test/DummyTest.php new file mode 100644 index 0000000..9638c11 --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/Test/DummyTest.php @@ -0,0 +1,18 @@ + ". + * + * Example ->error('Foo') would yield "error Foo". + * + * @return string[] + */ + abstract public function getLogs(); + + public function testImplements() + { + $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger()); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $logger = $this->getLogger(); + $logger->{$level}($message, array('user' => 'Bob')); + $logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + $level.' message of level '.$level.' with context: Bob', + $level.' message of level '.$level.' with context: Bob', + ); + $this->assertEquals($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $logger = $this->getLogger(); + $logger->log('invalid level', 'Foo'); + } + + public function testContextReplacement() + { + $logger = $this->getLogger(); + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('info {Message {nothing} Bob Bar a}'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString')); + } else { + $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString')); + } + $dummy->expects($this->once()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->getLogger()->warning($dummy); + + $expected = array('warning DUMMY'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $closed = fopen('php://memory', 'r'); + fclose($closed); + + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest), + 'object' => new \DateTime, + 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, + ); + + $this->getLogger()->warning('Crazy context data', $context); + + $expected = array('warning Crazy context data'); + $this->assertEquals($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->getLogger(); + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + 'warning Random message', + 'critical Uncaught Exception!' + ); + $this->assertEquals($expected, $this->getLogs()); + } +} diff --git a/www/multitube/vendor/psr/log/Psr/Log/Test/TestLogger.php b/www/multitube/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 0000000..1be3230 --- /dev/null +++ b/www/multitube/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,147 @@ + $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + $this->recordsByLevel = []; + } +} diff --git a/www/multitube/vendor/psr/log/README.md b/www/multitube/vendor/psr/log/README.md new file mode 100644 index 0000000..a9f20c4 --- /dev/null +++ b/www/multitube/vendor/psr/log/README.md @@ -0,0 +1,58 @@ +PSR Log +======= + +This repository holds all interfaces/classes/traits related to +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md). + +Note that this is not a logger of its own. It is merely an interface that +describes a logger. See the specification for more details. + +Installation +------------ + +```bash +composer require psr/log +``` + +Usage +----- + +If you need a logger, you can use the interface like this: + +```php +logger = $logger; + } + + public function doSomething() + { + if ($this->logger) { + $this->logger->info('Doing work'); + } + + try { + $this->doSomethingElse(); + } catch (Exception $exception) { + $this->logger->error('Oh no!', array('exception' => $exception)); + } + + // do something useful + } +} +``` + +You can then pick one of the implementations of the interface to get a logger. + +If you want to implement the interface, you can require this package and +implement `Psr\Log\LoggerInterface` in your code. Please read the +[specification text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +for details. diff --git a/www/multitube/vendor/psr/log/composer.json b/www/multitube/vendor/psr/log/composer.json new file mode 100644 index 0000000..3f6d4ee --- /dev/null +++ b/www/multitube/vendor/psr/log/composer.json @@ -0,0 +1,26 @@ +{ + "name": "psr/log", + "description": "Common interface for logging libraries", + "keywords": ["psr", "psr-3", "log"], + "homepage": "https://github.com/php-fig/log", + "license": "MIT", + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "require": { + "php": ">=5.3.0" + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/.gitignore b/www/multitube/vendor/rybakit/arguments-resolver/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/www/multitube/vendor/rybakit/arguments-resolver/.travis.yml b/www/multitube/vendor/rybakit/arguments-resolver/.travis.yml new file mode 100644 index 0000000..da0067c --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/.travis.yml @@ -0,0 +1,17 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - 7.0 + - hhvm + +before_script: + - composer install + +script: phpunit --coverage-clover coverage.clover + +after_script: + - wget https://scrutinizer-ci.com/ocular.phar + - php ocular.phar code-coverage:upload --format=php-clover coverage.clover diff --git a/www/multitube/vendor/rybakit/arguments-resolver/LICENSE b/www/multitube/vendor/rybakit/arguments-resolver/LICENSE new file mode 100644 index 0000000..a5c469b --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2017 Eugene Leonovich + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/www/multitube/vendor/rybakit/arguments-resolver/README.md b/www/multitube/vendor/rybakit/arguments-resolver/README.md new file mode 100644 index 0000000..c62e13a --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/README.md @@ -0,0 +1,181 @@ +ArgumentsResolver +================= +[![Build Status](https://secure.travis-ci.org/rybakit/arguments-resolver.svg?branch=master)](http://travis-ci.org/rybakit/arguments-resolver) +[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/rybakit/arguments-resolver/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/rybakit/arguments-resolver/?branch=master) +[![Code Coverage](https://scrutinizer-ci.com/g/rybakit/arguments-resolver/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/rybakit/arguments-resolver/?branch=master) + +ArgumentsResolver allows you to determine the arguments to pass to a function or method. + + +## Installation + +The recommended way to install ArgumentsResolver is through [Composer](http://getcomposer.org): + +```sh +$ composer require rybakit/arguments-resolver +``` + + +## Usage example + +```php +use ArgumentsResolver\InDepthArgumentsResolver; + +$greet = function ($username, DateTime $date, $greeting = 'Hello %s!') { + // ... +}; + +$parameters = [ + 'Welcome %s!', + ['foo'], + new DateTime(), + 'username' => 'Stranger', + 'bar', +]; + +$arguments = (new InDepthArgumentsResolver($greet))->resolve($parameters); +print_r($arguments); +``` + +The above example will output: + +```php +Array +( + [0] => Stranger + [1] => DateTime Object (...) + [2] => Welcome %s! +) +``` + + +## Resolvers + +The library ships with two resolvers, the [InDepthArgumentsResolver](#indepthargumentsresolver) and [NamedArgumentsResolver](#namedargumentsresolver). +They both expect a function to be supplied as a single constructor argument. The function can be any [callable](http://php.net/manual/en/language.types.callable.php), [a string representing a class method](http://php.net/manual/en/reflectionmethod.construct.php#refsect1-reflectionmethod.construct-parameters) or an instance of [ReflectionFunctionAbstract](http://php.net/manual/en/class.reflectionfunctionabstract.php): + +```php +new InDepthArgumentsResolver(['MyClass', 'myMethod']); +new InDepthArgumentsResolver([new MyClass(), 'myMethod']); +new InDepthArgumentsResolver(['MyClass', 'myStaticMethod']); +new InDepthArgumentsResolver('MyClass::myStaticMethod'); +new InDepthArgumentsResolver('MyClass::__construct'); +new InDepthArgumentsResolver(['MyClass', '__construct']); +new InDepthArgumentsResolver(new MyInvokableClass()); +new InDepthArgumentsResolver(function ($foo) {}); +new InDepthArgumentsResolver('MyNamespace\my_function'); +new InDepthArgumentsResolver(new ReflectionMethod('MyClass', 'myMethod')); +new InDepthArgumentsResolver(new ReflectionFunction('MyNamespace\my_function')); +``` + +There is also an utility class which helps in creating a reflection instance: + +```php +use ArgumentsResolver\ReflectionFactory; + +$reflection = ReflectionFactory::create('MyClass::__construct'); +$resolver = new InDepthArgumentsResolver($reflection); +``` + + +#### InDepthArgumentsResolver + +In the `InDepthArgumentsResolver`, the decision about whether an argument matched the parameter value or not +is influenced by multiple factors, namely the argument's type, the class hierarchy (if it's an object), +the argument name and the argument position. + +To clarify, consider each circumstance in turn: + +*Argument type* + +```php +function foo(array $array, stdClass $object, callable $callable) {} + +(new InDepthArgumentsResolver('foo'))->resolve([ + ... + function () {}, // $callable + ... + new stdClass(), // $object + ... + [42], // $array + ... +]); +``` + +*Class hierarchy* + +```php +function foo(Exception $e, RuntimeException $re) {} + +(new InDepthArgumentsResolver('foo'))->resolve([ + ... + new RuntimeException(), // $re + ... + new Exception(), // $e + ... +]); +``` + +*Argument name* + +```php +function foo($a, $b) {} + +(new InDepthArgumentsResolver('foo'))->resolve([ + ... + 'c' => 3, + 'b' => 2, // $b + 'a' => 1, // $a + ... +]); +``` + +*Argument position* + +```php +function foo($a, $b) {} + +(new InDepthArgumentsResolver('foo'))->resolve([ + 1, // $a + 2, // $b + ... +]); +``` + +#### NamedArgumentsResolver + +The `NamedArgumentsResolver` is a very simple resolver which does the matching only by the argument name. +Therefore this requires parameters to be an associative array: + +```php +function foo($a, array $b, $c = null) {} + +(new NamedArgumentsResolver('foo'))->resolve([ + ... + 'b' => [], // $b + 'a' => 1, // $a + 'c' => 'bar', // $c + ... +]); +``` + + +## Tests + +ArgumentsResolver uses [PHPUnit](http://phpunit.de) for unit testing. +In order to run the tests, you'll first need to setup the test suite using composer: + +```sh +$ composer install +``` + +You can then run the tests: + +```sh +$ phpunit +``` + + +## License + +ArgumentsResolver is released under the MIT License. See the bundled [LICENSE](LICENSE) file for details. diff --git a/www/multitube/vendor/rybakit/arguments-resolver/composer.json b/www/multitube/vendor/rybakit/arguments-resolver/composer.json new file mode 100644 index 0000000..f21796c --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/composer.json @@ -0,0 +1,32 @@ +{ + "name": "rybakit/arguments-resolver", + "description": "ArgumentsResolver allows you to determine the arguments to pass to a function or method.", + "keywords": ["arguments", "parameters", "function", "method", "callable", "reflection", "injection", "invoke", "resolver"], + "homepage": "https://github.com/rybakit/arguments-resolver", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Eugene Leonovich", + "email": "gen.work@gmail.com" + } + ], + "require": { + "php": "^5.4|^7.0" + }, + "autoload": { + "psr-4": { + "ArgumentsResolver\\": "src/" + } + }, + "autoload-dev" : { + "psr-4": { + "ArgumentsResolver\\Tests\\": "tests/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/phpunit.xml.dist b/www/multitube/vendor/rybakit/arguments-resolver/phpunit.xml.dist new file mode 100644 index 0000000..f4810c9 --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/phpunit.xml.dist @@ -0,0 +1,23 @@ + + + + + ./tests/ + + + + + ./src/ + + + diff --git a/www/multitube/vendor/rybakit/arguments-resolver/src/ArgumentsResolver.php b/www/multitube/vendor/rybakit/arguments-resolver/src/ArgumentsResolver.php new file mode 100644 index 0000000..098f9bc --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/src/ArgumentsResolver.php @@ -0,0 +1,78 @@ +reflection = $function instanceof \ReflectionFunctionAbstract + ? $function + : ReflectionFactory::create($function); + } + + /** + * Resolves function arguments. + * + * @param array $parameters + * + * @return array + * + * @throws UnresolvableArgumentException + */ + public function resolve(array $parameters) + { + if (!$number = $this->reflection->getNumberOfParameters()) { + return []; + } + + $arguments = array_fill(0, $number, null); + + foreach ($this->getParameters() as $pos => $parameter) { + $result = $this->match($parameter, $parameters); + + if ($result) { + $arguments[$pos] = $result[1]; + unset($parameters[$result[0]]); + continue; + } + + if ($parameter->isDefaultValueAvailable()) { + $arguments[$pos] = $parameter->getDefaultValue(); + continue; + } + + throw new UnresolvableArgumentException($parameter); + } + + return $arguments; + } + + /** + * Returns an array of reflection parameters. + * + * @return \ReflectionParameter[] + */ + protected function getParameters() + { + return $this->reflection->getParameters(); + } + + /** + * Returns the [key, value] pair if the parameter is matched or null otherwise. + * + * @param \ReflectionParameter $parameter + * @param array $parameters + * + * @return array|null + */ + abstract protected function match(\ReflectionParameter $parameter, array $parameters); +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/src/InDepthArgumentsResolver.php b/www/multitube/vendor/rybakit/arguments-resolver/src/InDepthArgumentsResolver.php new file mode 100644 index 0000000..ea65a64 --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/src/InDepthArgumentsResolver.php @@ -0,0 +1,118 @@ +sortedParameters) { + $this->sortedParameters = $this->reflection->getParameters(); + uasort($this->sortedParameters, [__CLASS__, 'compareParameters']); + } + + return $this->sortedParameters; + } + + /** + * {@inheritdoc} + */ + protected function match(\ReflectionParameter $parameter, array $parameters) + { + $found = null; + + foreach ($parameters as $key => $value) { + if (!self::matchType($parameter, $value)) { + continue; + } + + if ($key === $parameter->name) { + return [$key, $value]; + } + + if (!$found) { + $found = [$key, $value]; + } + } + + return $found; + } + + /** + * Checks if the value matches the parameter type. + * + * @param \ReflectionParameter $parameter + * @param mixed $value + * + * @return bool + */ + protected static function matchType(\ReflectionParameter $parameter, $value) + { + if ($class = $parameter->getClass()) { + return is_object($value) && $class->isInstance($value); + } + + if ($parameter->isArray()) { + return is_array($value); + } + + if ($parameter->isCallable()) { + return is_callable($value); + } + + return true; + } + + /** + * Compares reflection parameters by type and position. + * + * @param \ReflectionParameter $a + * @param \ReflectionParameter $b + * + * @return int + */ + private static function compareParameters(\ReflectionParameter $a, \ReflectionParameter $b) + { + if (0 !== $result = self::compareParameterClasses($a, $b)) { + return $result; + } + + if ($a->isArray() ^ $b->isArray()) { + return $b->isArray() << 1 - 1; + } + + if ($a->isCallable() ^ $b->isCallable()) { + return $b->isCallable() << 1 - 1; + } + + return $a->getPosition() - $b->getPosition(); + } + + /** + * Compares reflection parameters by class hierarchy. + * + * @param \ReflectionParameter $a + * @param \ReflectionParameter $b + * + * @return int + */ + private static function compareParameterClasses(\ReflectionParameter $a, \ReflectionParameter $b) + { + $a = $a->getClass(); + $b = $b->getClass(); + + if ($a && $b) { + return $a->isSubclassOf($b->name) ? -1 : (int) $b->isSubclassOf($a->name); + } + + return !$a - !$b; + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/src/NamedArgumentsResolver.php b/www/multitube/vendor/rybakit/arguments-resolver/src/NamedArgumentsResolver.php new file mode 100644 index 0000000..98a577c --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/src/NamedArgumentsResolver.php @@ -0,0 +1,16 @@ +name, $parameters)) { + return [$parameter->name, $parameters[$parameter->name]]; + } + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/src/ReflectionFactory.php b/www/multitube/vendor/rybakit/arguments-resolver/src/ReflectionFactory.php new file mode 100644 index 0000000..e881bbf --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/src/ReflectionFactory.php @@ -0,0 +1,30 @@ +newInstanceArgs($function); + } + + if (method_exists($function, '__invoke')) { + return new \ReflectionMethod($function, '__invoke'); + } + + return new \ReflectionFunction($function); + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/src/UnresolvableArgumentException.php b/www/multitube/vendor/rybakit/arguments-resolver/src/UnresolvableArgumentException.php new file mode 100644 index 0000000..386e40e --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/src/UnresolvableArgumentException.php @@ -0,0 +1,36 @@ +name, + $parameter->getPosition(), + static::getFunctionName($parameter->getDeclaringFunction()) + ); + } + + parent::__construct($message, $code, $previous); + } + + /** + * @param \ReflectionFunctionAbstract $reflection + * + * @return string + */ + protected static function getFunctionName(\ReflectionFunctionAbstract $reflection) + { + $name = $reflection->name.'()'; + + if ($reflection instanceof \ReflectionMethod) { + $name = $reflection->getDeclaringClass()->name.'::'.$name; + } + + return $name; + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/tests/ArgumentsResolverTest.php b/www/multitube/vendor/rybakit/arguments-resolver/tests/ArgumentsResolverTest.php new file mode 100644 index 0000000..5b22ac5 --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/tests/ArgumentsResolverTest.php @@ -0,0 +1,68 @@ + 'baz', 'bar' => 'bar', 'foo' => 'foo']; + + $this->assertArguments($function, $arguments, $parameters); + } + + public function testResolvingOptional() + { + $function = function ($foo = 'foo', $bar = 'bar') {}; + $arguments = ['foo', 'bar']; + $parameters = []; + + $this->assertArguments($function, $arguments, $parameters); + } + + public function testResolvingEmpty() + { + $function = function () {}; + $arguments = []; + $parameters = ['foo' => 'foo']; + + $this->assertArguments($function, $arguments, $parameters); + } + + /** + * @expectedException \ArgumentsResolver\UnresolvableArgumentException + * @expectedExceptionMessage Unable to resolve argument + */ + public function testResolvingThrowsExceptionOnEmptyParameters() + { + $this->resolveArguments(function ($foo) {}, []); + } + + public function assertArguments(\Closure $function, array $expected, array $actual) + { + $this->assertSame($expected, $this->resolveArguments($function, $actual)); + } + + /** + * @param \Closure $function + * @param array $parameters + * + * @return array + */ + protected function resolveArguments(\Closure $function, array $parameters) + { + $reflection = new \ReflectionFunction($function); + $resolver = $this->createResolver($reflection); + + return $resolver->resolve($parameters); + } + + /** + * @param \ReflectionFunctionAbstract $function + * + * @return \ArgumentsResolver\ArgumentsResolver + */ + abstract protected function createResolver(\ReflectionFunctionAbstract $function); +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/tests/InDepthArgumentsResolverTest.php b/www/multitube/vendor/rybakit/arguments-resolver/tests/InDepthArgumentsResolverTest.php new file mode 100644 index 0000000..86100e6 --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/tests/InDepthArgumentsResolverTest.php @@ -0,0 +1,93 @@ +assertArguments($function, $arguments, $parameters); + } + + public function testResolvingOptionalByType() + { + $function = function (callable $foo = null, array $bar = []) {}; + $arguments = [null, []]; + $parameters = []; + + $this->assertArguments($function, $arguments, $parameters); + } + + public function testResolvingSameTypeByName() + { + $foo = (object) ['name' => 'foo']; + $bar = (object) ['name' => 'bar']; + + $function = function (\stdClass $foo, \stdClass $bar) {}; + $arguments = [$foo, $bar]; + $parameters = ['bar' => $bar, 'foo' => $foo]; + + $this->assertArguments($function, $arguments, $parameters); + } + + public function testResolvingByObjectHierarchy() + { + $foo = new \Exception(); + $bar = new \RuntimeException(); + + $function = function (\Exception $foo, \RuntimeException $bar) {}; + $arguments = [$foo, $bar]; + $parameters = [$bar, $foo]; + + $this->assertArguments($function, $arguments, $parameters); + } + + public function testResolvingByObjectHierarchyReversed() + { + $foo = new \RuntimeException(); + $bar = new \Exception(); + + $function = function (\RuntimeException $foo, \Exception $bar) {}; + $arguments = [$foo, $bar]; + $parameters = [$bar, $foo]; + + $this->assertArguments($function, $arguments, $parameters); + } + + /** + * @dataProvider provideInvalidParameterTypes + * @expectedException \ArgumentsResolver\UnresolvableArgumentException + * @expectedExceptionMessage Unable to resolve argument + */ + public function testResolvingThrowsExceptionOnInvalidType($function, $parameters) + { + $this->resolveArguments($function, $parameters); + } + + public function provideInvalidParameterTypes() + { + return [ + [function (array $foo) {}, [42]], + [function (callable $foo) {}, [42]], + [function (\stdClass $foo) {}, [42]], + ]; + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/tests/NamedArgumentsResolverTest.php b/www/multitube/vendor/rybakit/arguments-resolver/tests/NamedArgumentsResolverTest.php new file mode 100644 index 0000000..97a6fde --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/tests/NamedArgumentsResolverTest.php @@ -0,0 +1,16 @@ +assertInstanceOf('ReflectionFunctionAbstract', $reflection); + $this->assertSame($expectedName, self::getFunctionName($reflection)); + } + + public function provideFunctionData() + { + $testClass = new TestClass(); + $testClassName = get_class($testClass); + + return [ + [$testClassName.'::foo', [$testClassName, 'foo']], + [$testClassName.'::foo', [$testClass, 'foo']], + [$testClassName.'::bar', [$testClassName, 'bar']], + [$testClassName.'::bar', $testClassName.'::bar'], + [$testClassName.'::__construct', [$testClassName, '__construct']], + [$testClassName.'::__construct', [$testClass, '__construct']], + [$testClassName.'::__invoke', $testClass], + ['Closure::__invoke', function () {}], + ['abs', 'abs'], + ]; + } + + /** + * @param \ReflectionFunctionAbstract $reflection + * + * @return string + */ + protected static function getFunctionName(\ReflectionFunctionAbstract $reflection) + { + if (!$reflection instanceof \ReflectionMethod) { + return $reflection->name; + } + + $class = $reflection->getDeclaringClass()->name; + + // see https://github.com/facebook/hhvm/issues/3874 + if (0 === strpos($class, 'Closure')) { + $class = 'Closure'; + } + + return $class.'::'.$reflection->name; + } +} diff --git a/www/multitube/vendor/rybakit/arguments-resolver/tests/TestClass.php b/www/multitube/vendor/rybakit/arguments-resolver/tests/TestClass.php new file mode 100644 index 0000000..d6479bc --- /dev/null +++ b/www/multitube/vendor/rybakit/arguments-resolver/tests/TestClass.php @@ -0,0 +1,22 @@ +getParameters(); + $exception = new UnresolvableArgumentException($parameters[0]); + + $this->assertRegExp( + sprintf('/^Unable to resolve argument \$\w+ \(#0\) of %s\(\)\.$/', preg_quote($expectedName, '/')), + $exception->getMessage() + ); + } + + public function provideReflectionData() + { + $functionName = 'abs'; + $methodName = __NAMESPACE__.'\TestClass::foo'; + + return [ + [$functionName, new \ReflectionFunction($functionName)], + [$methodName, new \ReflectionMethod($methodName)], + ]; + } +} diff --git a/www/multitube/vendor/symfony/console/.gitignore b/www/multitube/vendor/symfony/console/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/www/multitube/vendor/symfony/console/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/www/multitube/vendor/symfony/console/Application.php b/www/multitube/vendor/symfony/console/Application.php new file mode 100644 index 0000000..e9e3def --- /dev/null +++ b/www/multitube/vendor/symfony/console/Application.php @@ -0,0 +1,1276 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\HelpCommand; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleExceptionEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\DebugFormatterHelper; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Helper\ProcessHelper; +use Symfony\Component\Console\Helper\QuestionHelper; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\StreamableInputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Debug\ErrorHandler; +use Symfony\Component\Debug\Exception\FatalThrowableError; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; + +/** + * An Application is the container for a collection of commands. + * + * It is the main entry point of a Console application. + * + * This class is optimized for a standard CLI environment. + * + * Usage: + * + * $app = new Application('myapp', '1.0 (stable)'); + * $app->add(new SimpleCommand()); + * $app->run(); + * + * @author Fabien Potencier + */ +class Application +{ + private $commands = []; + private $wantHelps = false; + private $runningCommand; + private $name; + private $version; + private $commandLoader; + private $catchExceptions = true; + private $autoExit = true; + private $definition; + private $helperSet; + private $dispatcher; + private $terminal; + private $defaultCommand; + private $singleCommand = false; + private $initialized; + + /** + * @param string $name The name of the application + * @param string $version The version of the application + */ + public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') + { + $this->name = $name; + $this->version = $version; + $this->terminal = new Terminal(); + $this->defaultCommand = 'list'; + } + + public function setDispatcher(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + public function setCommandLoader(CommandLoaderInterface $commandLoader) + { + $this->commandLoader = $commandLoader; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + * + * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}. + */ + public function run(InputInterface $input = null, OutputInterface $output = null) + { + putenv('LINES='.$this->terminal->getHeight()); + putenv('COLUMNS='.$this->terminal->getWidth()); + + if (null === $input) { + $input = new ArgvInput(); + } + + if (null === $output) { + $output = new ConsoleOutput(); + } + + $renderException = function ($e) use ($output) { + if (!$e instanceof \Exception) { + $e = class_exists(FatalThrowableError::class) ? new FatalThrowableError($e) : new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine()); + } + if ($output instanceof ConsoleOutputInterface) { + $this->renderException($e, $output->getErrorOutput()); + } else { + $this->renderException($e, $output); + } + }; + if ($phpHandler = set_exception_handler($renderException)) { + restore_exception_handler(); + if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) { + $debugHandler = true; + } elseif ($debugHandler = $phpHandler[0]->setExceptionHandler($renderException)) { + $phpHandler[0]->setExceptionHandler($debugHandler); + } + } + + if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { + @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), \E_USER_DEPRECATED); + } + + $this->configureIO($input, $output); + + try { + $exitCode = $this->doRun($input, $output); + } catch (\Exception $e) { + if (!$this->catchExceptions) { + throw $e; + } + + $renderException($e); + + $exitCode = $e->getCode(); + if (is_numeric($exitCode)) { + $exitCode = (int) $exitCode; + if (0 === $exitCode) { + $exitCode = 1; + } + } else { + $exitCode = 1; + } + } finally { + // if the exception handler changed, keep it + // otherwise, unregister $renderException + if (!$phpHandler) { + if (set_exception_handler($renderException) === $renderException) { + restore_exception_handler(); + } + restore_exception_handler(); + } elseif (!$debugHandler) { + $finalHandler = $phpHandler[0]->setExceptionHandler(null); + if ($finalHandler !== $renderException) { + $phpHandler[0]->setExceptionHandler($finalHandler); + } + } + } + + if ($this->autoExit) { + if ($exitCode > 255) { + $exitCode = 255; + } + + exit($exitCode); + } + + return $exitCode; + } + + /** + * Runs the current application. + * + * @return int 0 if everything went fine, or an error code + */ + public function doRun(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--version', '-V'], true)) { + $output->writeln($this->getLongVersion()); + + return 0; + } + + try { + // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument. + $input->bind($this->getDefinition()); + } catch (ExceptionInterface $e) { + // Errors must be ignored, full binding/validation happens later when the command is known. + } + + $name = $this->getCommandName($input); + if (true === $input->hasParameterOption(['--help', '-h'], true)) { + if (!$name) { + $name = 'help'; + $input = new ArrayInput(['command_name' => $this->defaultCommand]); + } else { + $this->wantHelps = true; + } + } + + if (!$name) { + $name = $this->defaultCommand; + $definition = $this->getDefinition(); + $definition->setArguments(array_merge( + $definition->getArguments(), + [ + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), + ] + )); + } + + try { + $e = $this->runningCommand = null; + // the command name MUST be the first element of the input + $command = $this->find($name); + } catch (\Exception $e) { + } catch (\Throwable $e) { + } + if (null !== $e) { + if (null !== $this->dispatcher) { + $event = new ConsoleErrorEvent($input, $output, $e); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $e = $event->getError(); + + if (0 === $event->getExitCode()) { + return 0; + } + } + + throw $e; + } + + $this->runningCommand = $command; + $exitCode = $this->doRunCommand($command, $input, $output); + $this->runningCommand = null; + + return $exitCode; + } + + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Get the helper set associated with the command. + * + * @return HelperSet The HelperSet instance associated with this command + */ + public function getHelperSet() + { + if (!$this->helperSet) { + $this->helperSet = $this->getDefaultHelperSet(); + } + + return $this->helperSet; + } + + public function setDefinition(InputDefinition $definition) + { + $this->definition = $definition; + } + + /** + * Gets the InputDefinition related to this Application. + * + * @return InputDefinition The InputDefinition instance + */ + public function getDefinition() + { + if (!$this->definition) { + $this->definition = $this->getDefaultInputDefinition(); + } + + if ($this->singleCommand) { + $inputDefinition = $this->definition; + $inputDefinition->setArguments(); + + return $inputDefinition; + } + + return $this->definition; + } + + /** + * Gets the help message. + * + * @return string A help message + */ + public function getHelp() + { + return $this->getLongVersion(); + } + + /** + * Gets whether to catch exceptions or not during commands execution. + * + * @return bool Whether to catch exceptions or not during commands execution + */ + public function areExceptionsCaught() + { + return $this->catchExceptions; + } + + /** + * Sets whether to catch exceptions or not during commands execution. + * + * @param bool $boolean Whether to catch exceptions or not during commands execution + */ + public function setCatchExceptions($boolean) + { + $this->catchExceptions = (bool) $boolean; + } + + /** + * Gets whether to automatically exit after a command execution or not. + * + * @return bool Whether to automatically exit after a command execution or not + */ + public function isAutoExitEnabled() + { + return $this->autoExit; + } + + /** + * Sets whether to automatically exit after a command execution or not. + * + * @param bool $boolean Whether to automatically exit after a command execution or not + */ + public function setAutoExit($boolean) + { + $this->autoExit = (bool) $boolean; + } + + /** + * Gets the name of the application. + * + * @return string The application name + */ + public function getName() + { + return $this->name; + } + + /** + * Sets the application name. + * + * @param string $name The application name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * Gets the application version. + * + * @return string The application version + */ + public function getVersion() + { + return $this->version; + } + + /** + * Sets the application version. + * + * @param string $version The application version + */ + public function setVersion($version) + { + $this->version = $version; + } + + /** + * Returns the long version of the application. + * + * @return string The long application version + */ + public function getLongVersion() + { + if ('UNKNOWN' !== $this->getName()) { + if ('UNKNOWN' !== $this->getVersion()) { + return sprintf('%s %s', $this->getName(), $this->getVersion()); + } + + return $this->getName(); + } + + return 'Console Tool'; + } + + /** + * Registers a new command. + * + * @param string $name The command name + * + * @return Command The newly created command + */ + public function register($name) + { + return $this->add(new Command($name)); + } + + /** + * Adds an array of command objects. + * + * If a Command is not enabled it will not be added. + * + * @param Command[] $commands An array of commands + */ + public function addCommands(array $commands) + { + foreach ($commands as $command) { + $this->add($command); + } + } + + /** + * Adds a command object. + * + * If a command with the same name already exists, it will be overridden. + * If the command is not enabled it will not be added. + * + * @return Command|null The registered command if enabled or null + */ + public function add(Command $command) + { + $this->init(); + + $command->setApplication($this); + + if (!$command->isEnabled()) { + $command->setApplication(null); + + return null; + } + + // Will throw if the command is not correctly initialized. + $command->getDefinition(); + + if (!$command->getName()) { + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', \get_class($command))); + } + + $this->commands[$command->getName()] = $command; + + foreach ($command->getAliases() as $alias) { + $this->commands[$alias] = $command; + } + + return $command; + } + + /** + * Returns a registered command by name or alias. + * + * @param string $name The command name or alias + * + * @return Command A Command object + * + * @throws CommandNotFoundException When given command name does not exist + */ + public function get($name) + { + $this->init(); + + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); + } + + // When the command has a different name than the one used at the command loader level + if (!isset($this->commands[$name])) { + throw new CommandNotFoundException(sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name)); + } + + $command = $this->commands[$name]; + + if ($this->wantHelps) { + $this->wantHelps = false; + + $helpCommand = $this->get('help'); + $helpCommand->setCommand($command); + + return $helpCommand; + } + + return $command; + } + + /** + * Returns true if the command exists, false otherwise. + * + * @param string $name The command name or alias + * + * @return bool true if the command exists, false otherwise + */ + public function has($name) + { + $this->init(); + + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name))); + } + + /** + * Returns an array of all unique namespaces used by currently registered commands. + * + * It does not return the global namespace which always exists. + * + * @return string[] An array of namespaces + */ + public function getNamespaces() + { + $namespaces = []; + foreach ($this->all() as $command) { + if ($command->isHidden()) { + continue; + } + + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName())); + + foreach ($command->getAliases() as $alias) { + $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias)); + } + } + + return array_values(array_unique(array_filter($namespaces))); + } + + /** + * Finds a registered namespace by a name or an abbreviation. + * + * @param string $namespace A namespace or abbreviation to search for + * + * @return string A registered namespace + * + * @throws CommandNotFoundException When namespace is incorrect or ambiguous + */ + public function findNamespace($namespace) + { + $allNamespaces = $this->getNamespaces(); + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace); + $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces); + + if (empty($namespaces)) { + $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace); + + if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) { + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + + $message .= implode("\n ", $alternatives); + } + + throw new CommandNotFoundException($message, $alternatives); + } + + $exact = \in_array($namespace, $namespaces, true); + if (\count($namespaces) > 1 && !$exact) { + throw new CommandNotFoundException(sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces)); + } + + return $exact ? $namespace : reset($namespaces); + } + + /** + * Finds a command by name or alias. + * + * Contrary to get, this command tries to find the best + * match if you give it an abbreviation of a name or alias. + * + * @param string $name A command name or a command alias + * + * @return Command A Command instance + * + * @throws CommandNotFoundException When command name is incorrect or ambiguous + */ + public function find($name) + { + $this->init(); + + $aliases = []; + + foreach ($this->commands as $command) { + foreach ($command->getAliases() as $alias) { + if (!$this->has($alias)) { + $this->commands[$alias] = $command; + } + } + } + + if ($this->has($name)) { + return $this->get($name); + } + + $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); + $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); + $commands = preg_grep('{^'.$expr.'}', $allCommands); + + if (empty($commands)) { + $commands = preg_grep('{^'.$expr.'}i', $allCommands); + } + + // if no commands matched or we just matched namespaces + if (empty($commands) || \count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { + if (false !== $pos = strrpos($name, ':')) { + // check if a namespace exists and contains commands + $this->findNamespace(substr($name, 0, $pos)); + } + + $message = sprintf('Command "%s" is not defined.', $name); + + if ($alternatives = $this->findAlternatives($name, $allCommands)) { + // remove hidden commands + $alternatives = array_filter($alternatives, function ($name) { + return !$this->get($name)->isHidden(); + }); + + if (1 == \count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + $message .= implode("\n ", $alternatives); + } + + throw new CommandNotFoundException($message, array_values($alternatives)); + } + + // filter out aliases for commands which are already on the list + if (\count($commands) > 1) { + $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use (&$commandList, $commands, &$aliases) { + if (!$commandList[$nameOrAlias] instanceof Command) { + $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias); + } + + $commandName = $commandList[$nameOrAlias]->getName(); + + $aliases[$nameOrAlias] = $commandName; + + return $commandName === $nameOrAlias || !\in_array($commandName, $commands); + })); + } + + $exact = \in_array($name, $commands, true) || isset($aliases[$name]); + if (\count($commands) > 1 && !$exact) { + $usableWidth = $this->terminal->getWidth() - 10; + $abbrevs = array_values($commands); + $maxLen = 0; + foreach ($abbrevs as $abbrev) { + $maxLen = max(Helper::strlen($abbrev), $maxLen); + } + $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { + if ($commandList[$cmd]->isHidden()) { + return false; + } + + $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); + + return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; + }, array_values($commands)); + $suggestions = $this->getAbbreviationSuggestions(array_filter($abbrevs)); + + throw new CommandNotFoundException(sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), array_values($commands)); + } + + return $this->get($exact ? $name : reset($commands)); + } + + /** + * Gets the commands (registered in the given namespace if provided). + * + * The array keys are the full names and the values the command instances. + * + * @param string $namespace A namespace name + * + * @return Command[] An array of Command instances + */ + public function all($namespace = null) + { + $this->init(); + + if (null === $namespace) { + if (!$this->commandLoader) { + return $this->commands; + } + + $commands = $this->commands; + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + + return $commands; + } + + $commands = []; + foreach ($this->commands as $name => $command) { + if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { + $commands[$name] = $command; + } + } + + if ($this->commandLoader) { + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1) && $this->has($name)) { + $commands[$name] = $this->get($name); + } + } + } + + return $commands; + } + + /** + * Returns an array of possible abbreviations given a set of names. + * + * @param array $names An array of names + * + * @return array An array of abbreviations + */ + public static function getAbbreviations($names) + { + $abbrevs = []; + foreach ($names as $name) { + for ($len = \strlen($name); $len > 0; --$len) { + $abbrev = substr($name, 0, $len); + $abbrevs[$abbrev][] = $name; + } + } + + return $abbrevs; + } + + /** + * Renders a caught exception. + */ + public function renderException(\Exception $e, OutputInterface $output) + { + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + + $this->doRenderException($e, $output); + + if (null !== $this->runningCommand) { + $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } + + protected function doRenderException(\Exception $e, OutputInterface $output) + { + do { + $message = trim($e->getMessage()); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $title = sprintf(' [%s%s] ', \get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::strlen($title); + } else { + $len = 0; + } + + $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX; + // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 + if (\defined('HHVM_VERSION') && $width > 1 << 31) { + $width = 1 << 31; + } + $lines = []; + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : [] as $line) { + foreach ($this->splitStringByWidth($line, $width - 4) as $line) { + // pre-format lines to get the right string length + $lineLength = Helper::strlen($line) + 4; + $lines[] = [$line, $lineLength]; + + $len = max($lineLength, $len); + } + } + + $messages = []; + if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + } + $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + } + foreach ($lines as $line) { + $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); + } + $messages[] = $emptyLine; + $messages[] = ''; + + $output->writeln($messages, OutputInterface::VERBOSITY_QUIET); + + if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $output->writeln('Exception trace:', OutputInterface::VERBOSITY_QUIET); + + // exception related properties + $trace = $e->getTrace(); + + array_unshift($trace, [ + 'function' => '', + 'file' => $e->getFile() ?: 'n/a', + 'line' => $e->getLine() ?: 'n/a', + 'args' => [], + ]); + + for ($i = 0, $count = \count($trace); $i < $count; ++$i) { + $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; + $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : ''; + $function = isset($trace[$i]['function']) ? $trace[$i]['function'] : ''; + $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a'; + $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a'; + + $output->writeln(sprintf(' %s%s at %s:%s', $class, $function ? $type.$function.'()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET); + } + + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } while ($e = $e->getPrevious()); + } + + /** + * Tries to figure out the terminal width in which this application runs. + * + * @return int|null + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. + */ + protected function getTerminalWidth() + { + @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), \E_USER_DEPRECATED); + + return $this->terminal->getWidth(); + } + + /** + * Tries to figure out the terminal height in which this application runs. + * + * @return int|null + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. + */ + protected function getTerminalHeight() + { + @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), \E_USER_DEPRECATED); + + return $this->terminal->getHeight(); + } + + /** + * Tries to figure out the terminal dimensions based on the current environment. + * + * @return array Array containing width and height + * + * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. + */ + public function getTerminalDimensions() + { + @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), \E_USER_DEPRECATED); + + return [$this->terminal->getWidth(), $this->terminal->getHeight()]; + } + + /** + * Sets terminal dimensions. + * + * Can be useful to force terminal dimensions for functional tests. + * + * @param int $width The width + * @param int $height The height + * + * @return $this + * + * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. + */ + public function setTerminalDimensions($width, $height) + { + @trigger_error(sprintf('The "%s()" method is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), \E_USER_DEPRECATED); + + putenv('COLUMNS='.$width); + putenv('LINES='.$height); + + return $this; + } + + /** + * Configures the input and output instances based on the user arguments and options. + */ + protected function configureIO(InputInterface $input, OutputInterface $output) + { + if (true === $input->hasParameterOption(['--ansi'], true)) { + $output->setDecorated(true); + } elseif (true === $input->hasParameterOption(['--no-ansi'], true)) { + $output->setDecorated(false); + } + + if (true === $input->hasParameterOption(['--no-interaction', '-n'], true)) { + $input->setInteractive(false); + } elseif (\function_exists('posix_isatty')) { + $inputStream = null; + + if ($input instanceof StreamableInputInterface) { + $inputStream = $input->getStream(); + } + + // This check ensures that calling QuestionHelper::setInputStream() works + // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream) + if (!$inputStream && $this->getHelperSet()->has('question')) { + $inputStream = $this->getHelperSet()->get('question')->getInputStream(false); + } + + if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { + $input->setInteractive(false); + } + } + + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; + case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; + case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; + case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; + default: $shellVerbosity = 0; break; + } + + if (true === $input->hasParameterOption(['--quiet', '-q'], true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); + $shellVerbosity = -1; + } else { + if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + $shellVerbosity = 3; + } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + $shellVerbosity = 2; + } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { + $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + $shellVerbosity = 1; + } + } + + if (-1 === $shellVerbosity) { + $input->setInteractive(false); + } + + putenv('SHELL_VERBOSITY='.$shellVerbosity); + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; + } + + /** + * Runs the current command. + * + * If an event dispatcher has been attached to the application, + * events are also dispatched during the life-cycle of the command. + * + * @return int 0 if everything went fine, or an error code + */ + protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) + { + foreach ($command->getHelperSet() as $helper) { + if ($helper instanceof InputAwareInterface) { + $helper->setInput($input); + } + } + + if (null === $this->dispatcher) { + return $command->run($input, $output); + } + + // bind before the console.command event, so the listeners have access to input options/arguments + try { + $command->mergeApplicationDefinition(); + $input->bind($command->getDefinition()); + } catch (ExceptionInterface $e) { + // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition + } + + $event = new ConsoleCommandEvent($command, $input, $output); + $e = null; + + try { + $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event); + + if ($event->commandShouldRun()) { + $exitCode = $command->run($input, $output); + } else { + $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; + } + } catch (\Exception $e) { + } catch (\Throwable $e) { + } + if (null !== $e) { + if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { + $x = $e instanceof \Exception ? $e : new FatalThrowableError($e); + $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode()); + $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); + + if ($x !== $event->getException()) { + $e = $event->getException(); + } + } + $event = new ConsoleErrorEvent($input, $output, $e, $command); + $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); + $e = $event->getError(); + + if (0 === $exitCode = $event->getExitCode()) { + $e = null; + } + } + + $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); + $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); + + if (null !== $e) { + throw $e; + } + + return $event->getExitCode(); + } + + /** + * Gets the name of the command based on input. + * + * @return string|null + */ + protected function getCommandName(InputInterface $input) + { + return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument(); + } + + /** + * Gets the default input definition. + * + * @return InputDefinition An InputDefinition instance + */ + protected function getDefaultInputDefinition() + { + return new InputDefinition([ + new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), + + new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'), + new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), + new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), + new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), + new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'), + new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'), + new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'), + ]); + } + + /** + * Gets the default commands that should always be available. + * + * @return Command[] An array of default Command instances + */ + protected function getDefaultCommands() + { + return [new HelpCommand(), new ListCommand()]; + } + + /** + * Gets the default helper set with the helpers that should always be available. + * + * @return HelperSet A HelperSet instance + */ + protected function getDefaultHelperSet() + { + return new HelperSet([ + new FormatterHelper(), + new DebugFormatterHelper(), + new ProcessHelper(), + new QuestionHelper(), + ]); + } + + /** + * Returns abbreviated suggestions in string format. + * + * @param array $abbrevs Abbreviated suggestions to convert + * + * @return string A formatted string of abbreviated suggestions + */ + private function getAbbreviationSuggestions($abbrevs) + { + return ' '.implode("\n ", $abbrevs); + } + + /** + * Returns the namespace part of the command name. + * + * This method is not part of public API and should not be used directly. + * + * @param string $name The full name of the command + * @param string $limit The maximum number of parts of the namespace + * + * @return string The namespace of the command + */ + public function extractNamespace($name, $limit = null) + { + $parts = explode(':', $name, -1); + + return implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit)); + } + + /** + * Finds alternative of $name among $collection, + * if nothing is found in $collection, try in $abbrevs. + * + * @param string $name The string + * @param iterable $collection The collection + * + * @return string[] A sorted array of similar string + */ + private function findAlternatives($name, $collection) + { + $threshold = 1e3; + $alternatives = []; + + $collectionParts = []; + foreach ($collection as $item) { + $collectionParts[$item] = explode(':', $item); + } + + foreach (explode(':', $name) as $i => $subname) { + foreach ($collectionParts as $collectionName => $parts) { + $exists = isset($alternatives[$collectionName]); + if (!isset($parts[$i]) && $exists) { + $alternatives[$collectionName] += $threshold; + continue; + } elseif (!isset($parts[$i])) { + continue; + } + + $lev = levenshtein($subname, $parts[$i]); + if ($lev <= \strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) { + $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev; + } elseif ($exists) { + $alternatives[$collectionName] += $threshold; + } + } + } + + foreach ($collection as $item) { + $lev = levenshtein($name, $item); + if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; + } + } + + $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); + ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE); + + return array_keys($alternatives); + } + + /** + * Sets the default Command name. + * + * @param string $commandName The Command name + * @param bool $isSingleCommand Set to true if there is only one command in this application + * + * @return self + */ + public function setDefaultCommand($commandName, $isSingleCommand = false) + { + $this->defaultCommand = $commandName; + + if ($isSingleCommand) { + // Ensure the command exist + $this->find($commandName); + + $this->singleCommand = true; + } + + return $this; + } + + /** + * @internal + */ + public function isSingleCommand() + { + return $this->singleCommand; + } + + private function splitStringByWidth($string, $width) + { + // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly. + // additionally, array_slice() is not enough as some character has doubled width. + // we need a function to split string not by character count but by string width + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return str_split($string, $width); + } + + $utf8String = mb_convert_encoding($string, 'utf8', $encoding); + $lines = []; + $line = ''; + foreach (preg_split('//u', $utf8String) as $char) { + // test if $char could be appended to current line + if (mb_strwidth($line.$char, 'utf8') <= $width) { + $line .= $char; + continue; + } + // if not, push current line to array and make new line + $lines[] = str_pad($line, $width); + $line = $char; + } + + $lines[] = \count($lines) ? str_pad($line, $width) : $line; + + mb_convert_variables($encoding, 'utf8', $lines); + + return $lines; + } + + /** + * Returns all namespaces of the command name. + * + * @param string $name The full name of the command + * + * @return string[] The namespaces of the command + */ + private function extractAllNamespaces($name) + { + // -1 as third argument is needed to skip the command short name when exploding + $parts = explode(':', $name, -1); + $namespaces = []; + + foreach ($parts as $part) { + if (\count($namespaces)) { + $namespaces[] = end($namespaces).':'.$part; + } else { + $namespaces[] = $part; + } + } + + return $namespaces; + } + + private function init() + { + if ($this->initialized) { + return; + } + $this->initialized = true; + + foreach ($this->getDefaultCommands() as $command) { + $this->add($command); + } + } +} diff --git a/www/multitube/vendor/symfony/console/CHANGELOG.md b/www/multitube/vendor/symfony/console/CHANGELOG.md new file mode 100644 index 0000000..6dba1a4 --- /dev/null +++ b/www/multitube/vendor/symfony/console/CHANGELOG.md @@ -0,0 +1,112 @@ +CHANGELOG +========= + +3.4.0 +----- + + * added `SHELL_VERBOSITY` env var to control verbosity + * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 + `ContainerCommandLoader` for commands lazy-loading + * added a case-insensitive command name matching fallback + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. + +3.3.0 +----- + +* added `ExceptionListener` +* added `AddConsoleCommandPass` (originally in FrameworkBundle) +* [BC BREAK] `Input::getOption()` no longer returns the default value for options + with value optional explicitly passed empty +* added console.error event to catch exceptions thrown by other listeners +* deprecated console.exception event in favor of console.error +* added ability to handle `CommandNotFoundException` through the + `console.error` event +* deprecated default validation in `SymfonyQuestionHelper::ask` + +3.2.0 +------ + +* added `setInputs()` method to CommandTester for ease testing of commands expecting inputs +* added `setStream()` and `getStream()` methods to Input (implement StreamableInputInterface) +* added StreamableInputInterface +* added LockableTrait + +3.1.0 +----- + + * added truncate method to FormatterHelper + * added setColumnWidth(s) method to Table + +2.8.3 +----- + + * remove readline support from the question helper as it caused issues + +2.8.0 +----- + + * use readline for user input in the question helper when available to allow + the use of arrow keys + +2.6.0 +----- + + * added a Process helper + * added a DebugFormatter helper + +2.5.0 +----- + + * deprecated the dialog helper (use the question helper instead) + * deprecated TableHelper in favor of Table + * deprecated ProgressHelper in favor of ProgressBar + * added ConsoleLogger + * added a question helper + * added a way to set the process name of a command + * added a way to set a default command instead of `ListCommand` + +2.4.0 +----- + + * added a way to force terminal dimensions + * added a convenient method to detect verbosity level + * [BC BREAK] made descriptors use output instead of returning a string + +2.3.0 +----- + + * added multiselect support to the select dialog helper + * added Table Helper for tabular data rendering + * added support for events in `Application` + * added a way to normalize EOLs in `ApplicationTester::getDisplay()` and `CommandTester::getDisplay()` + * added a way to set the progress bar progress via the `setCurrent` method + * added support for multiple InputOption shortcuts, written as `'-a|-b|-c'` + * added two additional verbosity levels, VERBOSITY_VERY_VERBOSE and VERBOSITY_DEBUG + +2.2.0 +----- + + * added support for colorization on Windows via ConEmu + * add a method to Dialog Helper to ask for a question and hide the response + * added support for interactive selections in console (DialogHelper::select()) + * added support for autocompletion as you type in Dialog Helper + +2.1.0 +----- + + * added ConsoleOutputInterface + * added the possibility to disable a command (Command::isEnabled()) + * added suggestions when a command does not exist + * added a --raw option to the list command + * added support for STDERR in the console output class (errors are now sent + to STDERR) + * made the defaults (helper set, commands, input definition) in Application + more easily customizable + * added support for the shell even if readline is not available + * added support for process isolation in Symfony shell via + `--process-isolation` switch + * added support for `--`, which disables options parsing after that point + (tokens will be parsed as arguments) diff --git a/www/multitube/vendor/symfony/console/Command/Command.php b/www/multitube/vendor/symfony/console/Command/Command.php new file mode 100644 index 0000000..d896f67 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Command/Command.php @@ -0,0 +1,666 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Exception\ExceptionInterface; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Base class for all commands. + * + * @author Fabien Potencier + */ +class Command +{ + /** + * @var string|null The default command name + */ + protected static $defaultName; + + private $application; + private $name; + private $processTitle; + private $aliases = []; + private $definition; + private $hidden = false; + private $help = ''; + private $description = ''; + private $ignoreValidationErrors = false; + private $applicationDefinitionMerged = false; + private $applicationDefinitionMergedWithArgs = false; + private $code; + private $synopsis = []; + private $usages = []; + private $helperSet; + + /** + * @return string|null The default command name or null when no default name is set + */ + public static function getDefaultName() + { + $class = static::class; + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + + /** + * @param string|null $name The name of the command; passing null means it must be set in configure() + * + * @throws LogicException When the command name is empty + */ + public function __construct($name = null) + { + $this->definition = new InputDefinition(); + + if (null !== $name || null !== $name = static::getDefaultName()) { + $this->setName($name); + } + + $this->configure(); + } + + /** + * Ignores validation errors. + * + * This is mainly useful for the help command. + */ + public function ignoreValidationErrors() + { + $this->ignoreValidationErrors = true; + } + + public function setApplication(Application $application = null) + { + $this->application = $application; + if ($application) { + $this->setHelperSet($application->getHelperSet()); + } else { + $this->helperSet = null; + } + } + + public function setHelperSet(HelperSet $helperSet) + { + $this->helperSet = $helperSet; + } + + /** + * Gets the helper set. + * + * @return HelperSet|null A HelperSet instance + */ + public function getHelperSet() + { + return $this->helperSet; + } + + /** + * Gets the application instance for this command. + * + * @return Application|null An Application instance + */ + public function getApplication() + { + return $this->application; + } + + /** + * Checks whether the command is enabled or not in the current environment. + * + * Override this to check for x or y and return false if the command can not + * run properly under the current conditions. + * + * @return bool + */ + public function isEnabled() + { + return true; + } + + /** + * Configures the current command. + */ + protected function configure() + { + } + + /** + * Executes the current command. + * + * This method is not abstract because you can use this class + * as a concrete class. In this case, instead of defining the + * execute() method, you set the code to execute by passing + * a Closure to the setCode() method. + * + * @return int|null null or 0 if everything went fine, or an error code + * + * @throws LogicException When this abstract method is not implemented + * + * @see setCode() + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + throw new LogicException('You must override the execute() method in the concrete command class.'); + } + + /** + * Interacts with the user. + * + * This method is executed before the InputDefinition is validated. + * This means that this is the only place where the command can + * interactively ask for values of missing required arguments. + */ + protected function interact(InputInterface $input, OutputInterface $output) + { + } + + /** + * Initializes the command after the input has been bound and before the input + * is validated. + * + * This is mainly useful when a lot of commands extends one main command + * where some things need to be initialized based on the input arguments and options. + * + * @see InputInterface::bind() + * @see InputInterface::validate() + */ + protected function initialize(InputInterface $input, OutputInterface $output) + { + } + + /** + * Runs the command. + * + * The code to execute is either defined directly with the + * setCode() method or by overriding the execute() method + * in a sub-class. + * + * @return int The command exit code + * + * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}. + * + * @see setCode() + * @see execute() + */ + public function run(InputInterface $input, OutputInterface $output) + { + // force the creation of the synopsis before the merge with the app definition + $this->getSynopsis(true); + $this->getSynopsis(false); + + // add the application arguments and options + $this->mergeApplicationDefinition(); + + // bind the input against the command specific arguments/options + try { + $input->bind($this->definition); + } catch (ExceptionInterface $e) { + if (!$this->ignoreValidationErrors) { + throw $e; + } + } + + $this->initialize($input, $output); + + if (null !== $this->processTitle) { + if (\function_exists('cli_set_process_title')) { + if (!@cli_set_process_title($this->processTitle)) { + if ('Darwin' === \PHP_OS) { + $output->writeln('Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.', OutputInterface::VERBOSITY_VERY_VERBOSE); + } else { + cli_set_process_title($this->processTitle); + } + } + } elseif (\function_exists('setproctitle')) { + setproctitle($this->processTitle); + } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) { + $output->writeln('Install the proctitle PECL to be able to change the process title.'); + } + } + + if ($input->isInteractive()) { + $this->interact($input, $output); + } + + // The command name argument is often omitted when a command is executed directly with its run() method. + // It would fail the validation if we didn't make sure the command argument is present, + // since it's required by the application. + if ($input->hasArgument('command') && null === $input->getArgument('command')) { + $input->setArgument('command', $this->getName()); + } + + $input->validate(); + + if ($this->code) { + $statusCode = \call_user_func($this->code, $input, $output); + } else { + $statusCode = $this->execute($input, $output); + } + + return is_numeric($statusCode) ? (int) $statusCode : 0; + } + + /** + * Sets the code to execute when running this command. + * + * If this method is used, it overrides the code defined + * in the execute() method. + * + * @param callable $code A callable(InputInterface $input, OutputInterface $output) + * + * @return $this + * + * @throws InvalidArgumentException + * + * @see execute() + */ + public function setCode(callable $code) + { + if ($code instanceof \Closure) { + $r = new \ReflectionFunction($code); + if (null === $r->getClosureThis()) { + if (\PHP_VERSION_ID < 70000) { + // Bug in PHP5: https://bugs.php.net/64761 + // This means that we cannot bind static closures and therefore we must + // ignore any errors here. There is no way to test if the closure is + // bindable. + $code = @\Closure::bind($code, $this); + } else { + $code = \Closure::bind($code, $this); + } + } + } + + $this->code = $code; + + return $this; + } + + /** + * Merges the application definition with the command definition. + * + * This method is not part of public API and should not be used directly. + * + * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments + */ + public function mergeApplicationDefinition($mergeArgs = true) + { + if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) { + return; + } + + $this->definition->addOptions($this->application->getDefinition()->getOptions()); + + $this->applicationDefinitionMerged = true; + + if ($mergeArgs) { + $currentArguments = $this->definition->getArguments(); + $this->definition->setArguments($this->application->getDefinition()->getArguments()); + $this->definition->addArguments($currentArguments); + + $this->applicationDefinitionMergedWithArgs = true; + } + } + + /** + * Sets an array of argument and option instances. + * + * @param array|InputDefinition $definition An array of argument and option instances or a definition instance + * + * @return $this + */ + public function setDefinition($definition) + { + if ($definition instanceof InputDefinition) { + $this->definition = $definition; + } else { + $this->definition->setDefinition($definition); + } + + $this->applicationDefinitionMerged = false; + + return $this; + } + + /** + * Gets the InputDefinition attached to this Command. + * + * @return InputDefinition An InputDefinition instance + */ + public function getDefinition() + { + if (null === $this->definition) { + throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class)); + } + + return $this->definition; + } + + /** + * Gets the InputDefinition to be used to create representations of this Command. + * + * Can be overridden to provide the original command representation when it would otherwise + * be changed by merging with the application InputDefinition. + * + * This method is not part of public API and should not be used directly. + * + * @return InputDefinition An InputDefinition instance + */ + public function getNativeDefinition() + { + return $this->getDefinition(); + } + + /** + * Adds an argument. + * + * @param string $name The argument name + * @param int|null $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL + * @param string $description A description text + * @param string|string[]|null $default The default value (for InputArgument::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + * + * @return $this + */ + public function addArgument($name, $mode = null, $description = '', $default = null) + { + $this->definition->addArgument(new InputArgument($name, $mode, $description, $default)); + + return $this; + } + + /** + * Adds an option. + * + * @param string $name The option name + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the InputOption::VALUE_* constants + * @param string $description A description text + * @param string|string[]|int|bool|null $default The default value (must be null for InputOption::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + * + * @return $this + */ + public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null) + { + $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default)); + + return $this; + } + + /** + * Sets the name of the command. + * + * This method can set both the namespace and the name if + * you separate them by a colon (:) + * + * $command->setName('foo:bar'); + * + * @param string $name The command name + * + * @return $this + * + * @throws InvalidArgumentException When the name is invalid + */ + public function setName($name) + { + $this->validateName($name); + + $this->name = $name; + + return $this; + } + + /** + * Sets the process title of the command. + * + * This feature should be used only when creating a long process command, + * like a daemon. + * + * @param string $title The process title + * + * @return $this + */ + public function setProcessTitle($title) + { + $this->processTitle = $title; + + return $this; + } + + /** + * Returns the command name. + * + * @return string|null + */ + public function getName() + { + return $this->name; + } + + /** + * @param bool $hidden Whether or not the command should be hidden from the list of commands + * + * @return Command The current instance + */ + public function setHidden($hidden) + { + $this->hidden = (bool) $hidden; + + return $this; + } + + /** + * @return bool whether the command should be publicly shown or not + */ + public function isHidden() + { + return $this->hidden; + } + + /** + * Sets the description for the command. + * + * @param string $description The description for the command + * + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * Returns the description for the command. + * + * @return string The description for the command + */ + public function getDescription() + { + return $this->description; + } + + /** + * Sets the help for the command. + * + * @param string $help The help for the command + * + * @return $this + */ + public function setHelp($help) + { + $this->help = $help; + + return $this; + } + + /** + * Returns the help for the command. + * + * @return string The help for the command + */ + public function getHelp() + { + return $this->help; + } + + /** + * Returns the processed help for the command replacing the %command.name% and + * %command.full_name% patterns with the real values dynamically. + * + * @return string The processed help for the command + */ + public function getProcessedHelp() + { + $name = $this->name; + $isSingleCommand = $this->application && $this->application->isSingleCommand(); + + $placeholders = [ + '%command.name%', + '%command.full_name%', + ]; + $replacements = [ + $name, + $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'].' '.$name, + ]; + + return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription()); + } + + /** + * Sets the aliases for the command. + * + * @param string[] $aliases An array of aliases for the command + * + * @return $this + * + * @throws InvalidArgumentException When an alias is invalid + */ + public function setAliases($aliases) + { + if (!\is_array($aliases) && !$aliases instanceof \Traversable) { + throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable.'); + } + + foreach ($aliases as $alias) { + $this->validateName($alias); + } + + $this->aliases = $aliases; + + return $this; + } + + /** + * Returns the aliases for the command. + * + * @return array An array of aliases for the command + */ + public function getAliases() + { + return $this->aliases; + } + + /** + * Returns the synopsis for the command. + * + * @param bool $short Whether to show the short version of the synopsis (with options folded) or not + * + * @return string The synopsis + */ + public function getSynopsis($short = false) + { + $key = $short ? 'short' : 'long'; + + if (!isset($this->synopsis[$key])) { + $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short))); + } + + return $this->synopsis[$key]; + } + + /** + * Add a command usage example. + * + * @param string $usage The usage, it'll be prefixed with the command name + * + * @return $this + */ + public function addUsage($usage) + { + if (0 !== strpos($usage, $this->name)) { + $usage = sprintf('%s %s', $this->name, $usage); + } + + $this->usages[] = $usage; + + return $this; + } + + /** + * Returns alternative usages of the command. + * + * @return array + */ + public function getUsages() + { + return $this->usages; + } + + /** + * Gets a helper instance by name. + * + * @param string $name The helper name + * + * @return mixed The helper value + * + * @throws LogicException if no HelperSet is defined + * @throws InvalidArgumentException if the helper is not defined + */ + public function getHelper($name) + { + if (null === $this->helperSet) { + throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name)); + } + + return $this->helperSet->get($name); + } + + /** + * Validates a command name. + * + * It must be non-empty and parts can optionally be separated by ":". + * + * @param string $name + * + * @throws InvalidArgumentException When the name is invalid + */ + private function validateName($name) + { + if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) { + throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name)); + } + } +} diff --git a/www/multitube/vendor/symfony/console/Command/HelpCommand.php b/www/multitube/vendor/symfony/console/Command/HelpCommand.php new file mode 100644 index 0000000..2384776 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Command/HelpCommand.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * HelpCommand displays the help for a given command. + * + * @author Fabien Potencier + */ +class HelpCommand extends Command +{ + private $command; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->ignoreValidationErrors(); + + $this + ->setName('help') + ->setDefinition([ + new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'), + ]) + ->setDescription('Displays help for a command') + ->setHelp(<<<'EOF' +The %command.name% command displays help for a given command: + + php %command.full_name% list + +You can also output the help in other formats by using the --format option: + + php %command.full_name% --format=xml list + +To display the list of available commands, please use the list command. +EOF + ) + ; + } + + public function setCommand(Command $command) + { + $this->command = $command; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + if (null === $this->command) { + $this->command = $this->getApplication()->find($input->getArgument('command_name')); + } + + $helper = new DescriptorHelper(); + $helper->describe($output, $this->command, [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + ]); + + $this->command = null; + } +} diff --git a/www/multitube/vendor/symfony/console/Command/ListCommand.php b/www/multitube/vendor/symfony/console/Command/ListCommand.php new file mode 100644 index 0000000..7259b12 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Command/ListCommand.php @@ -0,0 +1,90 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * ListCommand displays the list of all available commands for the application. + * + * @author Fabien Potencier + */ +class ListCommand extends Command +{ + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('list') + ->setDefinition($this->createDefinition()) + ->setDescription('Lists commands') + ->setHelp(<<<'EOF' +The %command.name% command lists all commands: + + php %command.full_name% + +You can also display the commands for a specific namespace: + + php %command.full_name% test + +You can also output the information in other formats by using the --format option: + + php %command.full_name% --format=xml + +It's also possible to get raw list of commands (useful for embedding command runner): + + php %command.full_name% --raw +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + public function getNativeDefinition() + { + return $this->createDefinition(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $helper = new DescriptorHelper(); + $helper->describe($output, $this->getApplication(), [ + 'format' => $input->getOption('format'), + 'raw_text' => $input->getOption('raw'), + 'namespace' => $input->getArgument('namespace'), + ]); + } + + /** + * {@inheritdoc} + */ + private function createDefinition() + { + return new InputDefinition([ + new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), + new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), + ]); + } +} diff --git a/www/multitube/vendor/symfony/console/Command/LockableTrait.php b/www/multitube/vendor/symfony/console/Command/LockableTrait.php new file mode 100644 index 0000000..308ebf2 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Command/LockableTrait.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; + +/** + * Basic lock feature for commands. + * + * @author Geoffrey Brier + */ +trait LockableTrait +{ + /** @var Lock */ + private $lock; + + /** + * Locks a command. + * + * @return bool + */ + private function lock($name = null, $blocking = false) + { + if (!class_exists(SemaphoreStore::class)) { + throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.'); + } + + if (null !== $this->lock) { + throw new LogicException('A lock is already in place.'); + } + + if (SemaphoreStore::isSupported($blocking)) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(); + } + + $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); + if (!$this->lock->acquire($blocking)) { + $this->lock = null; + + return false; + } + + return true; + } + + /** + * Releases the command lock if there is one. + */ + private function release() + { + if ($this->lock) { + $this->lock->release(); + $this->lock = null; + } + } +} diff --git a/www/multitube/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php b/www/multitube/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php new file mode 100644 index 0000000..ca1029c --- /dev/null +++ b/www/multitube/vendor/symfony/console/CommandLoader/CommandLoaderInterface.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Robin Chalas + */ +interface CommandLoaderInterface +{ + /** + * Loads a command. + * + * @param string $name + * + * @return Command + * + * @throws CommandNotFoundException + */ + public function get($name); + + /** + * Checks if a command exists. + * + * @param string $name + * + * @return bool + */ + public function has($name); + + /** + * @return string[] All registered command names + */ + public function getNames(); +} diff --git a/www/multitube/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php b/www/multitube/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php new file mode 100644 index 0000000..8000c7d --- /dev/null +++ b/www/multitube/vendor/symfony/console/CommandLoader/ContainerCommandLoader.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Psr\Container\ContainerInterface; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * Loads commands from a PSR-11 container. + * + * @author Robin Chalas + */ +class ContainerCommandLoader implements CommandLoaderInterface +{ + private $container; + private $commandMap; + + /** + * @param ContainerInterface $container A container from which to load command services + * @param array $commandMap An array with command names as keys and service ids as values + */ + public function __construct(ContainerInterface $container, array $commandMap) + { + $this->container = $container; + $this->commandMap = $commandMap; + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->container->get($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->commandMap); + } +} diff --git a/www/multitube/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php b/www/multitube/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php new file mode 100644 index 0000000..d9c2055 --- /dev/null +++ b/www/multitube/vendor/symfony/console/CommandLoader/FactoryCommandLoader.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * A simple command loader using factories to instantiate commands lazily. + * + * @author Maxime Steinhausser + */ +class FactoryCommandLoader implements CommandLoaderInterface +{ + private $factories; + + /** + * @param callable[] $factories Indexed by command names + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->factories[$name]); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!isset($this->factories[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + $factory = $this->factories[$name]; + + return $factory(); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->factories); + } +} diff --git a/www/multitube/vendor/symfony/console/ConsoleEvents.php b/www/multitube/vendor/symfony/console/ConsoleEvents.php new file mode 100644 index 0000000..bf6cab9 --- /dev/null +++ b/www/multitube/vendor/symfony/console/ConsoleEvents.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +/** + * Contains all events dispatched by an Application. + * + * @author Francesco Levorato + */ +final class ConsoleEvents +{ + /** + * The COMMAND event allows you to attach listeners before any command is + * executed by the console. It also allows you to modify the command, input and output + * before they are handled to the command. + * + * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent") + */ + const COMMAND = 'console.command'; + + /** + * The TERMINATE event allows you to attach listeners after a command is + * executed by the console. + * + * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent") + */ + const TERMINATE = 'console.terminate'; + + /** + * The EXCEPTION event occurs when an uncaught exception appears + * while executing Command#run(). + * + * This event allows you to deal with the exception or + * to modify the thrown exception. + * + * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent") + * + * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead. + */ + const EXCEPTION = 'console.exception'; + + /** + * The ERROR event occurs when an uncaught exception or error appears. + * + * This event allows you to deal with the exception/error or + * to modify the thrown exception. + * + * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent") + */ + const ERROR = 'console.error'; +} diff --git a/www/multitube/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php b/www/multitube/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php new file mode 100644 index 0000000..f656d6a --- /dev/null +++ b/www/multitube/vendor/symfony/console/DependencyInjection/AddConsoleCommandPass.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\DependencyInjection; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\TypedReference; + +/** + * Registers console commands. + * + * @author Grégoire Pineau + */ +class AddConsoleCommandPass implements CompilerPassInterface +{ + private $commandLoaderServiceId; + private $commandTag; + + public function __construct($commandLoaderServiceId = 'console.command_loader', $commandTag = 'console.command') + { + $this->commandLoaderServiceId = $commandLoaderServiceId; + $this->commandTag = $commandTag; + } + + public function process(ContainerBuilder $container) + { + $commandServices = $container->findTaggedServiceIds($this->commandTag, true); + $lazyCommandMap = []; + $lazyCommandRefs = []; + $serviceIds = []; + $lazyServiceIds = []; + + foreach ($commandServices as $id => $tags) { + $definition = $container->getDefinition($id); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); + + $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); + + if (isset($tags[0]['command'])) { + $commandName = $tags[0]['command']; + } else { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); + } + $commandName = $class::getDefaultName(); + } + + if (null === $commandName) { + if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { + $commandId = $commandId.'_'.$id; + } + if (!$definition->isPublic() || $definition->isPrivate()) { + $container->setAlias($commandId, $id)->setPublic(true); + $id = $commandId; + } + $serviceIds[$commandId] = $id; + + continue; + } + + $serviceIds[$commandId] = $id; + $lazyServiceIds[$id] = true; + unset($tags[0]); + $lazyCommandMap[$commandName] = $id; + $lazyCommandRefs[$id] = new TypedReference($id, $class); + $aliases = []; + + foreach ($tags as $tag) { + if (isset($tag['command'])) { + $aliases[] = $tag['command']; + $lazyCommandMap[$tag['command']] = $id; + } + } + + $definition->addMethodCall('setName', [$commandName]); + + if ($aliases) { + $definition->addMethodCall('setAliases', [$aliases]); + } + } + + $container + ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) + ->setPublic(true) + ->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]); + + $container->setParameter('console.command.ids', $serviceIds); + $container->setParameter('console.lazy_command.ids', $lazyServiceIds); + } +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/ApplicationDescription.php b/www/multitube/vendor/symfony/console/Descriptor/ApplicationDescription.php new file mode 100644 index 0000000..65b5308 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/ApplicationDescription.php @@ -0,0 +1,157 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * @author Jean-François Simon + * + * @internal + */ +class ApplicationDescription +{ + const GLOBAL_NAMESPACE = '_global'; + + private $application; + private $namespace; + private $showHidden; + + /** + * @var array + */ + private $namespaces; + + /** + * @var Command[] + */ + private $commands; + + /** + * @var Command[] + */ + private $aliases; + + /** + * @param string|null $namespace + * @param bool $showHidden + */ + public function __construct(Application $application, $namespace = null, $showHidden = false) + { + $this->application = $application; + $this->namespace = $namespace; + $this->showHidden = $showHidden; + } + + /** + * @return array + */ + public function getNamespaces() + { + if (null === $this->namespaces) { + $this->inspectApplication(); + } + + return $this->namespaces; + } + + /** + * @return Command[] + */ + public function getCommands() + { + if (null === $this->commands) { + $this->inspectApplication(); + } + + return $this->commands; + } + + /** + * @param string $name + * + * @return Command + * + * @throws CommandNotFoundException + */ + public function getCommand($name) + { + if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name]; + } + + private function inspectApplication() + { + $this->commands = []; + $this->namespaces = []; + + $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null); + foreach ($this->sortCommands($all) as $namespace => $commands) { + $names = []; + + /** @var Command $command */ + foreach ($commands as $name => $command) { + if (!$command->getName() || (!$this->showHidden && $command->isHidden())) { + continue; + } + + if ($command->getName() === $name) { + $this->commands[$name] = $command; + } else { + $this->aliases[$name] = $command; + } + + $names[] = $name; + } + + $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names]; + } + } + + /** + * @return array + */ + private function sortCommands(array $commands) + { + $namespacedCommands = []; + $globalCommands = []; + $sortedCommands = []; + foreach ($commands as $name => $command) { + $key = $this->application->extractNamespace($name, 1); + if (\in_array($key, ['', self::GLOBAL_NAMESPACE], true)) { + $globalCommands[$name] = $command; + } else { + $namespacedCommands[$key][$name] = $command; + } + } + + if ($globalCommands) { + ksort($globalCommands); + $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands; + } + + if ($namespacedCommands) { + ksort($namespacedCommands); + foreach ($namespacedCommands as $key => $commandsSet) { + ksort($commandsSet); + $sortedCommands[$key] = $commandsSet; + } + } + + return $sortedCommands; + } +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/Descriptor.php b/www/multitube/vendor/symfony/console/Descriptor/Descriptor.php new file mode 100644 index 0000000..d25a708 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/Descriptor.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Jean-François Simon + * + * @internal + */ +abstract class Descriptor implements DescriptorInterface +{ + /** + * @var OutputInterface + */ + protected $output; + + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $this->output = $output; + + switch (true) { + case $object instanceof InputArgument: + $this->describeInputArgument($object, $options); + break; + case $object instanceof InputOption: + $this->describeInputOption($object, $options); + break; + case $object instanceof InputDefinition: + $this->describeInputDefinition($object, $options); + break; + case $object instanceof Command: + $this->describeCommand($object, $options); + break; + case $object instanceof Application: + $this->describeApplication($object, $options); + break; + default: + throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', \get_class($object))); + } + } + + /** + * Writes content to output. + * + * @param string $content + * @param bool $decorated + */ + protected function write($content, $decorated = false) + { + $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW); + } + + /** + * Describes an InputArgument instance. + * + * @return string|mixed + */ + abstract protected function describeInputArgument(InputArgument $argument, array $options = []); + + /** + * Describes an InputOption instance. + * + * @return string|mixed + */ + abstract protected function describeInputOption(InputOption $option, array $options = []); + + /** + * Describes an InputDefinition instance. + * + * @return string|mixed + */ + abstract protected function describeInputDefinition(InputDefinition $definition, array $options = []); + + /** + * Describes a Command instance. + * + * @return string|mixed + */ + abstract protected function describeCommand(Command $command, array $options = []); + + /** + * Describes an Application instance. + * + * @return string|mixed + */ + abstract protected function describeApplication(Application $application, array $options = []); +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/DescriptorInterface.php b/www/multitube/vendor/symfony/console/Descriptor/DescriptorInterface.php new file mode 100644 index 0000000..e3184a6 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/DescriptorInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Descriptor interface. + * + * @author Jean-François Simon + */ +interface DescriptorInterface +{ + /** + * Describes an object if supported. + * + * @param object $object + */ + public function describe(OutputInterface $output, $object, array $options = []); +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/JsonDescriptor.php b/www/multitube/vendor/symfony/console/Descriptor/JsonDescriptor.php new file mode 100644 index 0000000..e51c31d --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/JsonDescriptor.php @@ -0,0 +1,168 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * JSON descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class JsonDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeData($this->getInputArgumentData($argument), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeData($this->getInputOptionData($option), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeData($this->getInputDefinitionData($definition), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeData($this->getCommandData($command), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace, true); + $commands = []; + + foreach ($description->getCommands() as $command) { + $commands[] = $this->getCommandData($command); + } + + $data = []; + if ('UNKNOWN' !== $application->getName()) { + $data['application']['name'] = $application->getName(); + if ('UNKNOWN' !== $application->getVersion()) { + $data['application']['version'] = $application->getVersion(); + } + } + + $data['commands'] = $commands; + + if ($describedNamespace) { + $data['namespace'] = $describedNamespace; + } else { + $data['namespaces'] = array_values($description->getNamespaces()); + } + + $this->writeData($data, $options); + } + + /** + * Writes data as json. + */ + private function writeData(array $data, array $options) + { + $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; + + $this->write(json_encode($data, $flags)); + } + + /** + * @return array + */ + private function getInputArgumentData(InputArgument $argument) + { + return [ + 'name' => $argument->getName(), + 'is_required' => $argument->isRequired(), + 'is_array' => $argument->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), + 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), + ]; + } + + /** + * @return array + */ + private function getInputOptionData(InputOption $option) + { + return [ + 'name' => '--'.$option->getName(), + 'shortcut' => $option->getShortcut() ? '-'.str_replace('|', '|-', $option->getShortcut()) : '', + 'accept_value' => $option->acceptValue(), + 'is_value_required' => $option->isValueRequired(), + 'is_multiple' => $option->isArray(), + 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), + 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault(), + ]; + } + + /** + * @return array + */ + private function getInputDefinitionData(InputDefinition $definition) + { + $inputArguments = []; + foreach ($definition->getArguments() as $name => $argument) { + $inputArguments[$name] = $this->getInputArgumentData($argument); + } + + $inputOptions = []; + foreach ($definition->getOptions() as $name => $option) { + $inputOptions[$name] = $this->getInputOptionData($option); + } + + return ['arguments' => $inputArguments, 'options' => $inputOptions]; + } + + /** + * @return array + */ + private function getCommandData(Command $command) + { + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + return [ + 'name' => $command->getName(), + 'usage' => array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), + 'description' => $command->getDescription(), + 'help' => $command->getProcessedHelp(), + 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()), + 'hidden' => $command->isHidden(), + ]; + } +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/MarkdownDescriptor.php b/www/multitube/vendor/symfony/console/Descriptor/MarkdownDescriptor.php new file mode 100644 index 0000000..e624577 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/MarkdownDescriptor.php @@ -0,0 +1,182 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Markdown descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class MarkdownDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $decorated = $output->isDecorated(); + $output->setDecorated(false); + + parent::describe($output, $object, $options); + + $output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + protected function write($content, $decorated = true) + { + parent::write($content, $decorated); + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->write( + '#### `'.($argument->getName() ?: '')."`\n\n" + .($argument->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $argument->getDescription())."\n\n" : '') + .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n" + .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $name = '--'.$option->getName(); + if ($option->getShortcut()) { + $name .= '|-'.str_replace('|', '|-', $option->getShortcut()).''; + } + + $this->write( + '#### `'.$name.'`'."\n\n" + .($option->getDescription() ? preg_replace('/\s*[\r\n]\s*/', "\n", $option->getDescription())."\n\n" : '') + .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n" + .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n" + .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n" + .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`' + ); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + if ($showArguments = \count($definition->getArguments()) > 0) { + $this->write('### Arguments'); + foreach ($definition->getArguments() as $argument) { + $this->write("\n\n"); + $this->write($this->describeInputArgument($argument)); + } + } + + if (\count($definition->getOptions()) > 0) { + if ($showArguments) { + $this->write("\n\n"); + } + + $this->write('### Options'); + foreach ($definition->getOptions() as $option) { + $this->write("\n\n"); + $this->write($this->describeInputOption($option)); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + $this->write( + '`'.$command->getName()."`\n" + .str_repeat('-', Helper::strlen($command->getName()) + 2)."\n\n" + .($command->getDescription() ? $command->getDescription()."\n\n" : '') + .'### Usage'."\n\n" + .array_reduce(array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) { + return $carry.'* `'.$usage.'`'."\n"; + }) + ); + + if ($help = $command->getProcessedHelp()) { + $this->write("\n"); + $this->write($help); + } + + if ($command->getNativeDefinition()) { + $this->write("\n\n"); + $this->describeInputDefinition($command->getNativeDefinition()); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace); + $title = $this->getApplicationTitle($application); + + $this->write($title."\n".str_repeat('=', Helper::strlen($title))); + + foreach ($description->getNamespaces() as $namespace) { + if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->write("\n\n"); + $this->write('**'.$namespace['id'].':**'); + } + + $this->write("\n\n"); + $this->write(implode("\n", array_map(function ($commandName) use ($description) { + return sprintf('* [`%s`](#%s)', $commandName, str_replace(':', '', $description->getCommand($commandName)->getName())); + }, $namespace['commands']))); + } + + foreach ($description->getCommands() as $command) { + $this->write("\n\n"); + $this->write($this->describeCommand($command)); + } + } + + private function getApplicationTitle(Application $application) + { + if ('UNKNOWN' !== $application->getName()) { + if ('UNKNOWN' !== $application->getVersion()) { + return sprintf('%s %s', $application->getName(), $application->getVersion()); + } + + return $application->getName(); + } + + return 'Console Tool'; + } +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/TextDescriptor.php b/www/multitube/vendor/symfony/console/Descriptor/TextDescriptor.php new file mode 100644 index 0000000..9ca56ce --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/TextDescriptor.php @@ -0,0 +1,342 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * Text descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class TextDescriptor extends Descriptor +{ + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($argument->getDefault())); + } else { + $default = ''; + } + + $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName()); + $spacingWidth = $totalWidth - \strlen($argument->getName()); + + $this->writeText(sprintf(' %s %s%s%s', + $argument->getName(), + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()), + $default + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) { + $default = sprintf(' [default: %s]', $this->formatDefaultValue($option->getDefault())); + } else { + $default = ''; + } + + $value = ''; + if ($option->acceptValue()) { + $value = '='.strtoupper($option->getName()); + + if ($option->isValueOptional()) { + $value = '['.$value.']'; + } + } + + $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions([$option]); + $synopsis = sprintf('%s%s', + $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : ' ', + sprintf('--%s%s', $option->getName(), $value) + ); + + $spacingWidth = $totalWidth - Helper::strlen($synopsis); + + $this->writeText(sprintf(' %s %s%s%s%s', + $synopsis, + str_repeat(' ', $spacingWidth), + // + 4 = 2 spaces before , 2 spaces after + preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()), + $default, + $option->isArray() ? ' (multiple values allowed)' : '' + ), $options); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions()); + foreach ($definition->getArguments() as $argument) { + $totalWidth = max($totalWidth, Helper::strlen($argument->getName())); + } + + if ($definition->getArguments()) { + $this->writeText('Arguments:', $options); + $this->writeText("\n"); + foreach ($definition->getArguments() as $argument) { + $this->describeInputArgument($argument, array_merge($options, ['total_width' => $totalWidth])); + $this->writeText("\n"); + } + } + + if ($definition->getArguments() && $definition->getOptions()) { + $this->writeText("\n"); + } + + if ($definition->getOptions()) { + $laterOptions = []; + + $this->writeText('Options:', $options); + foreach ($definition->getOptions() as $option) { + if (\strlen($option->getShortcut()) > 1) { + $laterOptions[] = $option; + continue; + } + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + foreach ($laterOptions as $option) { + $this->writeText("\n"); + $this->describeInputOption($option, array_merge($options, ['total_width' => $totalWidth])); + } + } + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $command->getSynopsis(true); + $command->getSynopsis(false); + $command->mergeApplicationDefinition(false); + + $this->writeText('Usage:', $options); + foreach (array_merge([$command->getSynopsis(true)], $command->getAliases(), $command->getUsages()) as $usage) { + $this->writeText("\n"); + $this->writeText(' '.OutputFormatter::escape($usage), $options); + } + $this->writeText("\n"); + + $definition = $command->getNativeDefinition(); + if ($definition->getOptions() || $definition->getArguments()) { + $this->writeText("\n"); + $this->describeInputDefinition($definition, $options); + $this->writeText("\n"); + } + + if ($help = $command->getProcessedHelp()) { + $this->writeText("\n"); + $this->writeText('Help:', $options); + $this->writeText("\n"); + $this->writeText(' '.str_replace("\n", "\n ", $help), $options); + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null; + $description = new ApplicationDescription($application, $describedNamespace); + + if (isset($options['raw_text']) && $options['raw_text']) { + $width = $this->getColumnWidth($description->getCommands()); + + foreach ($description->getCommands() as $command) { + $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options); + $this->writeText("\n"); + } + } else { + if ('' != $help = $application->getHelp()) { + $this->writeText("$help\n\n", $options); + } + + $this->writeText("Usage:\n", $options); + $this->writeText(" command [options] [arguments]\n\n", $options); + + $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options); + + $this->writeText("\n"); + $this->writeText("\n"); + + $commands = $description->getCommands(); + $namespaces = $description->getNamespaces(); + if ($describedNamespace && $namespaces) { + // make sure all alias commands are included when describing a specific namespace + $describedNamespaceInfo = reset($namespaces); + foreach ($describedNamespaceInfo['commands'] as $name) { + $commands[$name] = $description->getCommand($name); + } + } + + // calculate max. width based on available commands per namespace + $width = $this->getColumnWidth(\call_user_func_array('array_merge', array_map(function ($namespace) use ($commands) { + return array_intersect($namespace['commands'], array_keys($commands)); + }, array_values($namespaces)))); + + if ($describedNamespace) { + $this->writeText(sprintf('Available commands for the "%s" namespace:', $describedNamespace), $options); + } else { + $this->writeText('Available commands:', $options); + } + + foreach ($namespaces as $namespace) { + $namespace['commands'] = array_filter($namespace['commands'], function ($name) use ($commands) { + return isset($commands[$name]); + }); + + if (!$namespace['commands']) { + continue; + } + + if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) { + $this->writeText("\n"); + $this->writeText(' '.$namespace['id'].'', $options); + } + + foreach ($namespace['commands'] as $name) { + $this->writeText("\n"); + $spacingWidth = $width - Helper::strlen($name); + $command = $commands[$name]; + $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : ''; + $this->writeText(sprintf(' %s%s%s', $name, str_repeat(' ', $spacingWidth), $commandAliases.$command->getDescription()), $options); + } + } + + $this->writeText("\n"); + } + } + + /** + * {@inheritdoc} + */ + private function writeText($content, array $options = []) + { + $this->write( + isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content, + isset($options['raw_output']) ? !$options['raw_output'] : true + ); + } + + /** + * Formats command aliases to show them in the command description. + * + * @return string + */ + private function getCommandAliasesText(Command $command) + { + $text = ''; + $aliases = $command->getAliases(); + + if ($aliases) { + $text = '['.implode('|', $aliases).'] '; + } + + return $text; + } + + /** + * Formats input option/argument default value. + * + * @param mixed $default + * + * @return string + */ + private function formatDefaultValue($default) + { + if (\INF === $default) { + return 'INF'; + } + + if (\is_string($default)) { + $default = OutputFormatter::escape($default); + } elseif (\is_array($default)) { + foreach ($default as $key => $value) { + if (\is_string($value)) { + $default[$key] = OutputFormatter::escape($value); + } + } + } + + return str_replace('\\\\', '\\', json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE)); + } + + /** + * @param (Command|string)[] $commands + * + * @return int + */ + private function getColumnWidth(array $commands) + { + $widths = []; + + foreach ($commands as $command) { + if ($command instanceof Command) { + $widths[] = Helper::strlen($command->getName()); + foreach ($command->getAliases() as $alias) { + $widths[] = Helper::strlen($alias); + } + } else { + $widths[] = Helper::strlen($command); + } + } + + return $widths ? max($widths) + 2 : 0; + } + + /** + * @param InputOption[] $options + * + * @return int + */ + private function calculateTotalWidthForOptions(array $options) + { + $totalWidth = 0; + foreach ($options as $option) { + // "-" + shortcut + ", --" + name + $nameLength = 1 + max(Helper::strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName()); + + if ($option->acceptValue()) { + $valueLength = 1 + Helper::strlen($option->getName()); // = + value + $valueLength += $option->isValueOptional() ? 2 : 0; // [ + ] + + $nameLength += $valueLength; + } + $totalWidth = max($totalWidth, $nameLength); + } + + return $totalWidth; + } +} diff --git a/www/multitube/vendor/symfony/console/Descriptor/XmlDescriptor.php b/www/multitube/vendor/symfony/console/Descriptor/XmlDescriptor.php new file mode 100644 index 0000000..2d25458 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Descriptor/XmlDescriptor.php @@ -0,0 +1,248 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Descriptor; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputOption; + +/** + * XML descriptor. + * + * @author Jean-François Simon + * + * @internal + */ +class XmlDescriptor extends Descriptor +{ + /** + * @return \DOMDocument + */ + public function getInputDefinitionDocument(InputDefinition $definition) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($definitionXML = $dom->createElement('definition')); + + $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments')); + foreach ($definition->getArguments() as $argument) { + $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument)); + } + + $definitionXML->appendChild($optionsXML = $dom->createElement('options')); + foreach ($definition->getOptions() as $option) { + $this->appendDocument($optionsXML, $this->getInputOptionDocument($option)); + } + + return $dom; + } + + /** + * @return \DOMDocument + */ + public function getCommandDocument(Command $command) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($commandXML = $dom->createElement('command')); + + $command->getSynopsis(); + $command->mergeApplicationDefinition(false); + + $commandXML->setAttribute('id', $command->getName()); + $commandXML->setAttribute('name', $command->getName()); + $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0); + + $commandXML->appendChild($usagesXML = $dom->createElement('usages')); + + foreach (array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) { + $usagesXML->appendChild($dom->createElement('usage', $usage)); + } + + $commandXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription()))); + + $commandXML->appendChild($helpXML = $dom->createElement('help')); + $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp()))); + + $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition()); + $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0)); + + return $dom; + } + + /** + * @param string|null $namespace + * + * @return \DOMDocument + */ + public function getApplicationDocument(Application $application, $namespace = null) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->appendChild($rootXml = $dom->createElement('symfony')); + + if ('UNKNOWN' !== $application->getName()) { + $rootXml->setAttribute('name', $application->getName()); + if ('UNKNOWN' !== $application->getVersion()) { + $rootXml->setAttribute('version', $application->getVersion()); + } + } + + $rootXml->appendChild($commandsXML = $dom->createElement('commands')); + + $description = new ApplicationDescription($application, $namespace, true); + + if ($namespace) { + $commandsXML->setAttribute('namespace', $namespace); + } + + foreach ($description->getCommands() as $command) { + $this->appendDocument($commandsXML, $this->getCommandDocument($command)); + } + + if (!$namespace) { + $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces')); + + foreach ($description->getNamespaces() as $namespaceDescription) { + $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace')); + $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']); + + foreach ($namespaceDescription['commands'] as $name) { + $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command')); + $commandXML->appendChild($dom->createTextNode($name)); + } + } + } + + return $dom; + } + + /** + * {@inheritdoc} + */ + protected function describeInputArgument(InputArgument $argument, array $options = []) + { + $this->writeDocument($this->getInputArgumentDocument($argument)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputOption(InputOption $option, array $options = []) + { + $this->writeDocument($this->getInputOptionDocument($option)); + } + + /** + * {@inheritdoc} + */ + protected function describeInputDefinition(InputDefinition $definition, array $options = []) + { + $this->writeDocument($this->getInputDefinitionDocument($definition)); + } + + /** + * {@inheritdoc} + */ + protected function describeCommand(Command $command, array $options = []) + { + $this->writeDocument($this->getCommandDocument($command)); + } + + /** + * {@inheritdoc} + */ + protected function describeApplication(Application $application, array $options = []) + { + $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null)); + } + + /** + * Appends document children to parent node. + */ + private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent) + { + foreach ($importedParent->childNodes as $childNode) { + $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true)); + } + } + + /** + * Writes DOM document. + */ + private function writeDocument(\DOMDocument $dom) + { + $dom->formatOutput = true; + $this->write($dom->saveXML()); + } + + /** + * @return \DOMDocument + */ + private function getInputArgumentDocument(InputArgument $argument) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('argument')); + $objectXML->setAttribute('name', $argument->getName()); + $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0); + $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($argument->getDescription())); + + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [var_export($argument->getDefault(), true)] : ($argument->getDefault() ? [$argument->getDefault()] : [])); + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + + return $dom; + } + + /** + * @return \DOMDocument + */ + private function getInputOptionDocument(InputOption $option) + { + $dom = new \DOMDocument('1.0', 'UTF-8'); + + $dom->appendChild($objectXML = $dom->createElement('option')); + $objectXML->setAttribute('name', '--'.$option->getName()); + $pos = strpos($option->getShortcut(), '|'); + if (false !== $pos) { + $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos)); + $objectXML->setAttribute('shortcuts', '-'.str_replace('|', '|-', $option->getShortcut())); + } else { + $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : ''); + } + $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0); + $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0); + $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0); + $objectXML->appendChild($descriptionXML = $dom->createElement('description')); + $descriptionXML->appendChild($dom->createTextNode($option->getDescription())); + + if ($option->acceptValue()) { + $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [var_export($option->getDefault(), true)] : ($option->getDefault() ? [$option->getDefault()] : [])); + $objectXML->appendChild($defaultsXML = $dom->createElement('defaults')); + + if (!empty($defaults)) { + foreach ($defaults as $default) { + $defaultsXML->appendChild($defaultXML = $dom->createElement('default')); + $defaultXML->appendChild($dom->createTextNode($default)); + } + } + } + + return $dom; + } +} diff --git a/www/multitube/vendor/symfony/console/Event/ConsoleCommandEvent.php b/www/multitube/vendor/symfony/console/Event/ConsoleCommandEvent.php new file mode 100644 index 0000000..2f517c1 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Event/ConsoleCommandEvent.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +/** + * Allows to do things before the command is executed, like skipping the command or changing the input. + * + * @author Fabien Potencier + */ +class ConsoleCommandEvent extends ConsoleEvent +{ + /** + * The return code for skipped commands, this will also be passed into the terminate event. + */ + const RETURN_CODE_DISABLED = 113; + + /** + * Indicates if the command should be run or skipped. + */ + private $commandShouldRun = true; + + /** + * Disables the command, so it won't be run. + * + * @return bool + */ + public function disableCommand() + { + return $this->commandShouldRun = false; + } + + /** + * Enables the command. + * + * @return bool + */ + public function enableCommand() + { + return $this->commandShouldRun = true; + } + + /** + * Returns true if the command is runnable, false otherwise. + * + * @return bool + */ + public function commandShouldRun() + { + return $this->commandShouldRun; + } +} diff --git a/www/multitube/vendor/symfony/console/Event/ConsoleErrorEvent.php b/www/multitube/vendor/symfony/console/Event/ConsoleErrorEvent.php new file mode 100644 index 0000000..51a5f56 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Event/ConsoleErrorEvent.php @@ -0,0 +1,83 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to handle throwables thrown while running a command. + * + * @author Wouter de Jong + */ +final class ConsoleErrorEvent extends ConsoleEvent +{ + private $error; + private $exitCode; + + public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null) + { + parent::__construct($command, $input, $output); + + $this->setError($error); + } + + /** + * Returns the thrown error/exception. + * + * @return \Throwable + */ + public function getError() + { + return $this->error; + } + + /** + * Replaces the thrown error/exception. + * + * @param \Throwable $error + */ + public function setError($error) + { + if (!$error instanceof \Throwable && !$error instanceof \Exception) { + throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', \is_object($error) ? \get_class($error) : \gettype($error))); + } + + $this->error = $error; + } + + /** + * Sets the exit code. + * + * @param int $exitCode The command exit code + */ + public function setExitCode($exitCode) + { + $this->exitCode = (int) $exitCode; + + $r = new \ReflectionProperty($this->error, 'code'); + $r->setAccessible(true); + $r->setValue($this->error, $this->exitCode); + } + + /** + * Gets the exit code. + * + * @return int The command exit code + */ + public function getExitCode() + { + return null !== $this->exitCode ? $this->exitCode : (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1); + } +} diff --git a/www/multitube/vendor/symfony/console/Event/ConsoleEvent.php b/www/multitube/vendor/symfony/console/Event/ConsoleEvent.php new file mode 100644 index 0000000..5440da2 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Event/ConsoleEvent.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\Event; + +/** + * Allows to inspect input and output of a command. + * + * @author Francesco Levorato + */ +class ConsoleEvent extends Event +{ + protected $command; + + private $input; + private $output; + + public function __construct(Command $command = null, InputInterface $input, OutputInterface $output) + { + $this->command = $command; + $this->input = $input; + $this->output = $output; + } + + /** + * Gets the command that is executed. + * + * @return Command|null A Command instance + */ + public function getCommand() + { + return $this->command; + } + + /** + * Gets the input instance. + * + * @return InputInterface An InputInterface instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance. + * + * @return OutputInterface An OutputInterface instance + */ + public function getOutput() + { + return $this->output; + } +} diff --git a/www/multitube/vendor/symfony/console/Event/ConsoleExceptionEvent.php b/www/multitube/vendor/symfony/console/Event/ConsoleExceptionEvent.php new file mode 100644 index 0000000..845119e --- /dev/null +++ b/www/multitube/vendor/symfony/console/Event/ConsoleExceptionEvent.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), \E_USER_DEPRECATED); + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to handle exception thrown in a command. + * + * @author Fabien Potencier + * + * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead. + */ +class ConsoleExceptionEvent extends ConsoleEvent +{ + private $exception; + private $exitCode; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) + { + parent::__construct($command, $input, $output); + + $this->setException($exception); + $this->exitCode = (int) $exitCode; + } + + /** + * Returns the thrown exception. + * + * @return \Exception The thrown exception + */ + public function getException() + { + return $this->exception; + } + + /** + * Replaces the thrown exception. + * + * This exception will be thrown if no response is set in the event. + * + * @param \Exception $exception The thrown exception + */ + public function setException(\Exception $exception) + { + $this->exception = $exception; + } + + /** + * Gets the exit code. + * + * @return int The command exit code + */ + public function getExitCode() + { + return $this->exitCode; + } +} diff --git a/www/multitube/vendor/symfony/console/Event/ConsoleTerminateEvent.php b/www/multitube/vendor/symfony/console/Event/ConsoleTerminateEvent.php new file mode 100644 index 0000000..b6a5d7c --- /dev/null +++ b/www/multitube/vendor/symfony/console/Event/ConsoleTerminateEvent.php @@ -0,0 +1,58 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Event; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Allows to manipulate the exit code of a command after its execution. + * + * @author Francesco Levorato + */ +class ConsoleTerminateEvent extends ConsoleEvent +{ + /** + * The exit code of the command. + * + * @var int + */ + private $exitCode; + + public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode) + { + parent::__construct($command, $input, $output); + + $this->setExitCode($exitCode); + } + + /** + * Sets the exit code. + * + * @param int $exitCode The command exit code + */ + public function setExitCode($exitCode) + { + $this->exitCode = (int) $exitCode; + } + + /** + * Gets the exit code. + * + * @return int The command exit code + */ + public function getExitCode() + { + return $this->exitCode; + } +} diff --git a/www/multitube/vendor/symfony/console/EventListener/ErrorListener.php b/www/multitube/vendor/symfony/console/EventListener/ErrorListener.php new file mode 100644 index 0000000..783c107 --- /dev/null +++ b/www/multitube/vendor/symfony/console/EventListener/ErrorListener.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\EventListener; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * @author James Halsall + * @author Robin Chalas + */ +class ErrorListener implements EventSubscriberInterface +{ + private $logger; + + public function __construct(LoggerInterface $logger = null) + { + $this->logger = $logger; + } + + public function onConsoleError(ConsoleErrorEvent $event) + { + if (null === $this->logger) { + return; + } + + $error = $event->getError(); + + if (!$inputString = $this->getInputString($event)) { + $this->logger->error('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]); + + return; + } + + $this->logger->error('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]); + } + + public function onConsoleTerminate(ConsoleTerminateEvent $event) + { + if (null === $this->logger) { + return; + } + + $exitCode = $event->getExitCode(); + + if (0 === $exitCode) { + return; + } + + if (!$inputString = $this->getInputString($event)) { + $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]); + + return; + } + + $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]); + } + + public static function getSubscribedEvents() + { + return [ + ConsoleEvents::ERROR => ['onConsoleError', -128], + ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128], + ]; + } + + private static function getInputString(ConsoleEvent $event) + { + $commandName = $event->getCommand() ? $event->getCommand()->getName() : null; + $input = $event->getInput(); + + if (method_exists($input, '__toString')) { + if ($commandName) { + return str_replace(["'$commandName'", "\"$commandName\""], $commandName, (string) $input); + } + + return (string) $input; + } + + return $commandName; + } +} diff --git a/www/multitube/vendor/symfony/console/Exception/CommandNotFoundException.php b/www/multitube/vendor/symfony/console/Exception/CommandNotFoundException.php new file mode 100644 index 0000000..d28fceb --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/CommandNotFoundException.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect command name typed in the console. + * + * @author Jérôme Tamarelle + */ +class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface +{ + private $alternatives; + + /** + * @param string $message Exception message to throw + * @param array $alternatives List of similar defined names + * @param int $code Exception code + * @param \Exception $previous Previous exception used for the exception chaining + */ + public function __construct($message, array $alternatives = [], $code = 0, \Exception $previous = null) + { + parent::__construct($message, $code, $previous); + + $this->alternatives = $alternatives; + } + + /** + * @return array A list of similar defined names + */ + public function getAlternatives() + { + return $this->alternatives; + } +} diff --git a/www/multitube/vendor/symfony/console/Exception/ExceptionInterface.php b/www/multitube/vendor/symfony/console/Exception/ExceptionInterface.php new file mode 100644 index 0000000..491cc4c --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * ExceptionInterface. + * + * @author Jérôme Tamarelle + */ +interface ExceptionInterface +{ +} diff --git a/www/multitube/vendor/symfony/console/Exception/InvalidArgumentException.php b/www/multitube/vendor/symfony/console/Exception/InvalidArgumentException.php new file mode 100644 index 0000000..07cc0b6 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/www/multitube/vendor/symfony/console/Exception/InvalidOptionException.php b/www/multitube/vendor/symfony/console/Exception/InvalidOptionException.php new file mode 100644 index 0000000..b2eec61 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/InvalidOptionException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * Represents an incorrect option name typed in the console. + * + * @author Jérôme Tamarelle + */ +class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/www/multitube/vendor/symfony/console/Exception/LogicException.php b/www/multitube/vendor/symfony/console/Exception/LogicException.php new file mode 100644 index 0000000..fc37b8d --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/LogicException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/www/multitube/vendor/symfony/console/Exception/RuntimeException.php b/www/multitube/vendor/symfony/console/Exception/RuntimeException.php new file mode 100644 index 0000000..51d7d80 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Exception/RuntimeException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Exception; + +/** + * @author Jérôme Tamarelle + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/www/multitube/vendor/symfony/console/Formatter/OutputFormatter.php b/www/multitube/vendor/symfony/console/Formatter/OutputFormatter.php new file mode 100644 index 0000000..abc8539 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Formatter/OutputFormatter.php @@ -0,0 +1,243 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Formatter class for console output. + * + * @author Konstantin Kudryashov + */ +class OutputFormatter implements OutputFormatterInterface +{ + private $decorated; + private $styles = []; + private $styleStack; + + /** + * Escapes "<" special char in given text. + * + * @param string $text Text to escape + * + * @return string Escaped text + */ + public static function escape($text) + { + $text = preg_replace('/([^\\\\]?) FormatterStyle" instances + */ + public function __construct($decorated = false, array $styles = []) + { + $this->decorated = (bool) $decorated; + + $this->setStyle('error', new OutputFormatterStyle('white', 'red')); + $this->setStyle('info', new OutputFormatterStyle('green')); + $this->setStyle('comment', new OutputFormatterStyle('yellow')); + $this->setStyle('question', new OutputFormatterStyle('black', 'cyan')); + + foreach ($styles as $name => $style) { + $this->setStyle($name, $style); + } + + $this->styleStack = new OutputFormatterStyleStack(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated($decorated) + { + $this->decorated = (bool) $decorated; + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->decorated; + } + + /** + * {@inheritdoc} + */ + public function setStyle($name, OutputFormatterStyleInterface $style) + { + $this->styles[strtolower($name)] = $style; + } + + /** + * {@inheritdoc} + */ + public function hasStyle($name) + { + return isset($this->styles[strtolower($name)]); + } + + /** + * {@inheritdoc} + */ + public function getStyle($name) + { + if (!$this->hasStyle($name)) { + throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name)); + } + + return $this->styles[strtolower($name)]; + } + + /** + * {@inheritdoc} + */ + public function format($message) + { + $message = (string) $message; + $offset = 0; + $output = ''; + $tagRegex = '[a-z][a-z0-9,_=;-]*+'; + preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE); + foreach ($matches[0] as $i => $match) { + $pos = $match[1]; + $text = $match[0]; + + if (0 != $pos && '\\' == $message[$pos - 1]) { + continue; + } + + // add the text up to the next tag + $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset)); + $offset = $pos + \strlen($text); + + // opening tag? + if ($open = '/' != $text[1]) { + $tag = $matches[1][$i][0]; + } else { + $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : ''; + } + + if (!$open && !$tag) { + // + $this->styleStack->pop(); + } elseif (false === $style = $this->createStyleFromString($tag)) { + $output .= $this->applyCurrentStyle($text); + } elseif ($open) { + $this->styleStack->push($style); + } else { + $this->styleStack->pop($style); + } + } + + $output .= $this->applyCurrentStyle(substr($message, $offset)); + + if (false !== strpos($output, "\0")) { + return strtr($output, ["\0" => '\\', '\\<' => '<']); + } + + return str_replace('\\<', '<', $output); + } + + /** + * @return OutputFormatterStyleStack + */ + public function getStyleStack() + { + return $this->styleStack; + } + + /** + * Tries to create new style instance from string. + * + * @param string $string + * + * @return OutputFormatterStyle|false false if string is not format string + */ + private function createStyleFromString($string) + { + if (isset($this->styles[$string])) { + return $this->styles[$string]; + } + + if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) { + return false; + } + + $style = new OutputFormatterStyle(); + foreach ($matches as $match) { + array_shift($match); + $match[0] = strtolower($match[0]); + + if ('fg' == $match[0]) { + $style->setForeground(strtolower($match[1])); + } elseif ('bg' == $match[0]) { + $style->setBackground(strtolower($match[1])); + } elseif ('options' === $match[0]) { + preg_match_all('([^,;]+)', strtolower($match[1]), $options); + $options = array_shift($options); + foreach ($options as $option) { + try { + $style->setOption($option); + } catch (\InvalidArgumentException $e) { + @trigger_error(sprintf('Unknown style options are deprecated since Symfony 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), \E_USER_DEPRECATED); + + return false; + } + } + } else { + return false; + } + } + + return $style; + } + + /** + * Applies current style from stack to text, if must be applied. + * + * @param string $text Input text + * + * @return string Styled text + */ + private function applyCurrentStyle($text) + { + return $this->isDecorated() && \strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text; + } +} diff --git a/www/multitube/vendor/symfony/console/Formatter/OutputFormatterInterface.php b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterInterface.php new file mode 100644 index 0000000..281e240 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterInterface.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter interface for console output. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterInterface +{ + /** + * Sets the decorated flag. + * + * @param bool $decorated Whether to decorate the messages or not + */ + public function setDecorated($decorated); + + /** + * Gets the decorated flag. + * + * @return bool true if the output will decorate messages, false otherwise + */ + public function isDecorated(); + + /** + * Sets a new style. + * + * @param string $name The style name + * @param OutputFormatterStyleInterface $style The style instance + */ + public function setStyle($name, OutputFormatterStyleInterface $style); + + /** + * Checks if output formatter has style with specified name. + * + * @param string $name + * + * @return bool + */ + public function hasStyle($name); + + /** + * Gets style options from style with specified name. + * + * @param string $name + * + * @return OutputFormatterStyleInterface + * + * @throws \InvalidArgumentException When style isn't defined + */ + public function getStyle($name); + + /** + * Formats a message according to the given styles. + * + * @param string $message The message to style + * + * @return string The styled message + */ + public function format($message); +} diff --git a/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyle.php b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyle.php new file mode 100644 index 0000000..7075c72 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyle.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Formatter style class for defining styles. + * + * @author Konstantin Kudryashov + */ +class OutputFormatterStyle implements OutputFormatterStyleInterface +{ + private static $availableForegroundColors = [ + 'black' => ['set' => 30, 'unset' => 39], + 'red' => ['set' => 31, 'unset' => 39], + 'green' => ['set' => 32, 'unset' => 39], + 'yellow' => ['set' => 33, 'unset' => 39], + 'blue' => ['set' => 34, 'unset' => 39], + 'magenta' => ['set' => 35, 'unset' => 39], + 'cyan' => ['set' => 36, 'unset' => 39], + 'white' => ['set' => 37, 'unset' => 39], + 'default' => ['set' => 39, 'unset' => 39], + ]; + private static $availableBackgroundColors = [ + 'black' => ['set' => 40, 'unset' => 49], + 'red' => ['set' => 41, 'unset' => 49], + 'green' => ['set' => 42, 'unset' => 49], + 'yellow' => ['set' => 43, 'unset' => 49], + 'blue' => ['set' => 44, 'unset' => 49], + 'magenta' => ['set' => 45, 'unset' => 49], + 'cyan' => ['set' => 46, 'unset' => 49], + 'white' => ['set' => 47, 'unset' => 49], + 'default' => ['set' => 49, 'unset' => 49], + ]; + private static $availableOptions = [ + 'bold' => ['set' => 1, 'unset' => 22], + 'underscore' => ['set' => 4, 'unset' => 24], + 'blink' => ['set' => 5, 'unset' => 25], + 'reverse' => ['set' => 7, 'unset' => 27], + 'conceal' => ['set' => 8, 'unset' => 28], + ]; + + private $foreground; + private $background; + private $options = []; + + /** + * Initializes output formatter style. + * + * @param string|null $foreground The style foreground color name + * @param string|null $background The style background color name + * @param array $options The style options + */ + public function __construct($foreground = null, $background = null, array $options = []) + { + if (null !== $foreground) { + $this->setForeground($foreground); + } + if (null !== $background) { + $this->setBackground($background); + } + if (\count($options)) { + $this->setOptions($options); + } + } + + /** + * {@inheritdoc} + */ + public function setForeground($color = null) + { + if (null === $color) { + $this->foreground = null; + + return; + } + + if (!isset(static::$availableForegroundColors[$color])) { + throw new InvalidArgumentException(sprintf('Invalid foreground color specified: "%s". Expected one of (%s).', $color, implode(', ', array_keys(static::$availableForegroundColors)))); + } + + $this->foreground = static::$availableForegroundColors[$color]; + } + + /** + * {@inheritdoc} + */ + public function setBackground($color = null) + { + if (null === $color) { + $this->background = null; + + return; + } + + if (!isset(static::$availableBackgroundColors[$color])) { + throw new InvalidArgumentException(sprintf('Invalid background color specified: "%s". Expected one of (%s).', $color, implode(', ', array_keys(static::$availableBackgroundColors)))); + } + + $this->background = static::$availableBackgroundColors[$color]; + } + + /** + * {@inheritdoc} + */ + public function setOption($option) + { + if (!isset(static::$availableOptions[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(static::$availableOptions)))); + } + + if (!\in_array(static::$availableOptions[$option], $this->options)) { + $this->options[] = static::$availableOptions[$option]; + } + } + + /** + * {@inheritdoc} + */ + public function unsetOption($option) + { + if (!isset(static::$availableOptions[$option])) { + throw new InvalidArgumentException(sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, implode(', ', array_keys(static::$availableOptions)))); + } + + $pos = array_search(static::$availableOptions[$option], $this->options); + if (false !== $pos) { + unset($this->options[$pos]); + } + } + + /** + * {@inheritdoc} + */ + public function setOptions(array $options) + { + $this->options = []; + + foreach ($options as $option) { + $this->setOption($option); + } + } + + /** + * {@inheritdoc} + */ + public function apply($text) + { + $setCodes = []; + $unsetCodes = []; + + if (null !== $this->foreground) { + $setCodes[] = $this->foreground['set']; + $unsetCodes[] = $this->foreground['unset']; + } + if (null !== $this->background) { + $setCodes[] = $this->background['set']; + $unsetCodes[] = $this->background['unset']; + } + if (\count($this->options)) { + foreach ($this->options as $option) { + $setCodes[] = $option['set']; + $unsetCodes[] = $option['unset']; + } + } + + if (0 === \count($setCodes)) { + return $text; + } + + return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes)); + } +} diff --git a/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php new file mode 100644 index 0000000..af171c2 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +/** + * Formatter style interface for defining styles. + * + * @author Konstantin Kudryashov + */ +interface OutputFormatterStyleInterface +{ + /** + * Sets style foreground color. + * + * @param string|null $color The color name + */ + public function setForeground($color = null); + + /** + * Sets style background color. + * + * @param string $color The color name + */ + public function setBackground($color = null); + + /** + * Sets some specific style option. + * + * @param string $option The option name + */ + public function setOption($option); + + /** + * Unsets some specific style option. + * + * @param string $option The option name + */ + public function unsetOption($option); + + /** + * Sets multiple style options at once. + */ + public function setOptions(array $options); + + /** + * Applies the style to a given text. + * + * @param string $text The text to style + * + * @return string + */ + public function apply($text); +} diff --git a/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php new file mode 100644 index 0000000..5066649 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Formatter/OutputFormatterStyleStack.php @@ -0,0 +1,109 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Formatter; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Jean-François Simon + */ +class OutputFormatterStyleStack +{ + /** + * @var OutputFormatterStyleInterface[] + */ + private $styles; + + private $emptyStyle; + + public function __construct(OutputFormatterStyleInterface $emptyStyle = null) + { + $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle(); + $this->reset(); + } + + /** + * Resets stack (ie. empty internal arrays). + */ + public function reset() + { + $this->styles = []; + } + + /** + * Pushes a style in the stack. + */ + public function push(OutputFormatterStyleInterface $style) + { + $this->styles[] = $style; + } + + /** + * Pops a style from the stack. + * + * @return OutputFormatterStyleInterface + * + * @throws InvalidArgumentException When style tags incorrectly nested + */ + public function pop(OutputFormatterStyleInterface $style = null) + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + if (null === $style) { + return array_pop($this->styles); + } + + foreach (array_reverse($this->styles, true) as $index => $stackedStyle) { + if ($style->apply('') === $stackedStyle->apply('')) { + $this->styles = \array_slice($this->styles, 0, $index); + + return $stackedStyle; + } + } + + throw new InvalidArgumentException('Incorrectly nested style tag found.'); + } + + /** + * Computes current style with stacks top codes. + * + * @return OutputFormatterStyle + */ + public function getCurrent() + { + if (empty($this->styles)) { + return $this->emptyStyle; + } + + return $this->styles[\count($this->styles) - 1]; + } + + /** + * @return $this + */ + public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle) + { + $this->emptyStyle = $emptyStyle; + + return $this; + } + + /** + * @return OutputFormatterStyleInterface + */ + public function getEmptyStyle() + { + return $this->emptyStyle; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/DebugFormatterHelper.php b/www/multitube/vendor/symfony/console/Helper/DebugFormatterHelper.php new file mode 100644 index 0000000..16d1175 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/DebugFormatterHelper.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * Helps outputting debug information when running an external program from a command. + * + * An external program can be a Process, an HTTP request, or anything else. + * + * @author Fabien Potencier + */ +class DebugFormatterHelper extends Helper +{ + private $colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default']; + private $started = []; + private $count = -1; + + /** + * Starts a debug formatting session. + * + * @param string $id The id of the formatting session + * @param string $message The message to display + * @param string $prefix The prefix to use + * + * @return string + */ + public function start($id, $message, $prefix = 'RUN') + { + $this->started[$id] = ['border' => ++$this->count % \count($this->colors)]; + + return sprintf("%s %s %s\n", $this->getBorder($id), $prefix, $message); + } + + /** + * Adds progress to a formatting session. + * + * @param string $id The id of the formatting session + * @param string $buffer The message to display + * @param bool $error Whether to consider the buffer as error + * @param string $prefix The prefix for output + * @param string $errorPrefix The prefix for error output + * + * @return string + */ + public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR') + { + $message = ''; + + if ($error) { + if (isset($this->started[$id]['out'])) { + $message .= "\n"; + unset($this->started[$id]['out']); + } + if (!isset($this->started[$id]['err'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $errorPrefix); + $this->started[$id]['err'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $errorPrefix), $buffer); + } else { + if (isset($this->started[$id]['err'])) { + $message .= "\n"; + unset($this->started[$id]['err']); + } + if (!isset($this->started[$id]['out'])) { + $message .= sprintf('%s %s ', $this->getBorder($id), $prefix); + $this->started[$id]['out'] = true; + } + + $message .= str_replace("\n", sprintf("\n%s %s ", $this->getBorder($id), $prefix), $buffer); + } + + return $message; + } + + /** + * Stops a formatting session. + * + * @param string $id The id of the formatting session + * @param string $message The message to display + * @param bool $successful Whether to consider the result as success + * @param string $prefix The prefix for the end output + * + * @return string + */ + public function stop($id, $message, $successful, $prefix = 'RES') + { + $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : ''; + + if ($successful) { + return sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + } + + $message = sprintf("%s%s %s %s\n", $trailingEOL, $this->getBorder($id), $prefix, $message); + + unset($this->started[$id]['out'], $this->started[$id]['err']); + + return $message; + } + + /** + * @param string $id The id of the formatting session + * + * @return string + */ + private function getBorder($id) + { + return sprintf(' ', $this->colors[$this->started[$id]['border']]); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'debug_formatter'; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/DescriptorHelper.php b/www/multitube/vendor/symfony/console/Helper/DescriptorHelper.php new file mode 100644 index 0000000..3055bae --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/DescriptorHelper.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Descriptor\JsonDescriptor; +use Symfony\Component\Console\Descriptor\MarkdownDescriptor; +use Symfony\Component\Console\Descriptor\TextDescriptor; +use Symfony\Component\Console\Descriptor\XmlDescriptor; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * This class adds helper method to describe objects in various formats. + * + * @author Jean-François Simon + */ +class DescriptorHelper extends Helper +{ + /** + * @var DescriptorInterface[] + */ + private $descriptors = []; + + public function __construct() + { + $this + ->register('txt', new TextDescriptor()) + ->register('xml', new XmlDescriptor()) + ->register('json', new JsonDescriptor()) + ->register('md', new MarkdownDescriptor()) + ; + } + + /** + * Describes an object if supported. + * + * Available options are: + * * format: string, the output format name + * * raw_text: boolean, sets output type as raw + * + * @param object $object + * + * @throws InvalidArgumentException when the given format is not supported + */ + public function describe(OutputInterface $output, $object, array $options = []) + { + $options = array_merge([ + 'raw_text' => false, + 'format' => 'txt', + ], $options); + + if (!isset($this->descriptors[$options['format']])) { + throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format'])); + } + + $descriptor = $this->descriptors[$options['format']]; + $descriptor->describe($output, $object, $options); + } + + /** + * Registers a descriptor. + * + * @param string $format + * + * @return $this + */ + public function register($format, DescriptorInterface $descriptor) + { + $this->descriptors[$format] = $descriptor; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'descriptor'; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/FormatterHelper.php b/www/multitube/vendor/symfony/console/Helper/FormatterHelper.php new file mode 100644 index 0000000..d6eccee --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/FormatterHelper.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatter; + +/** + * The Formatter class provides helpers to format messages. + * + * @author Fabien Potencier + */ +class FormatterHelper extends Helper +{ + /** + * Formats a message within a section. + * + * @param string $section The section name + * @param string $message The message + * @param string $style The style to apply to the section + * + * @return string The format section + */ + public function formatSection($section, $message, $style = 'info') + { + return sprintf('<%s>[%s] %s', $style, $section, $style, $message); + } + + /** + * Formats a message as a block of text. + * + * @param string|array $messages The message to write in the block + * @param string $style The style to apply to the whole block + * @param bool $large Whether to return a large block + * + * @return string The formatter message + */ + public function formatBlock($messages, $style, $large = false) + { + if (!\is_array($messages)) { + $messages = [$messages]; + } + + $len = 0; + $lines = []; + foreach ($messages as $message) { + $message = OutputFormatter::escape($message); + $lines[] = sprintf($large ? ' %s ' : ' %s ', $message); + $len = max(self::strlen($message) + ($large ? 4 : 2), $len); + } + + $messages = $large ? [str_repeat(' ', $len)] : []; + for ($i = 0; isset($lines[$i]); ++$i) { + $messages[] = $lines[$i].str_repeat(' ', $len - self::strlen($lines[$i])); + } + if ($large) { + $messages[] = str_repeat(' ', $len); + } + + for ($i = 0; isset($messages[$i]); ++$i) { + $messages[$i] = sprintf('<%s>%s', $style, $messages[$i], $style); + } + + return implode("\n", $messages); + } + + /** + * Truncates a message to the given length. + * + * @param string $message + * @param int $length + * @param string $suffix + * + * @return string + */ + public function truncate($message, $length, $suffix = '...') + { + $computedLength = $length - self::strlen($suffix); + + if ($computedLength > self::strlen($message)) { + return $message; + } + + return self::substr($message, 0, $length).$suffix; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'formatter'; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/Helper.php b/www/multitube/vendor/symfony/console/Helper/Helper.php new file mode 100644 index 0000000..0ddddf6 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/Helper.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * Helper is the base class for all helper classes. + * + * @author Fabien Potencier + */ +abstract class Helper implements HelperInterface +{ + protected $helperSet = null; + + /** + * {@inheritdoc} + */ + public function setHelperSet(HelperSet $helperSet = null) + { + $this->helperSet = $helperSet; + } + + /** + * {@inheritdoc} + */ + public function getHelperSet() + { + return $this->helperSet; + } + + /** + * Returns the length of a string, using mb_strwidth if it is available. + * + * @param string $string The string to check its length + * + * @return int The length of the string + */ + public static function strlen($string) + { + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return \strlen($string); + } + + return mb_strwidth($string, $encoding); + } + + /** + * Returns the subset of a string, using mb_substr if it is available. + * + * @param string $string String to subset + * @param int $from Start offset + * @param int|null $length Length to read + * + * @return string The string subset + */ + public static function substr($string, $from, $length = null) + { + if (false === $encoding = mb_detect_encoding($string, null, true)) { + return substr($string, $from, $length); + } + + return mb_substr($string, $from, $length, $encoding); + } + + public static function formatTime($secs) + { + static $timeFormats = [ + [0, '< 1 sec'], + [1, '1 sec'], + [2, 'secs', 1], + [60, '1 min'], + [120, 'mins', 60], + [3600, '1 hr'], + [7200, 'hrs', 3600], + [86400, '1 day'], + [172800, 'days', 86400], + ]; + + foreach ($timeFormats as $index => $format) { + if ($secs >= $format[0]) { + if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0]) + || $index == \count($timeFormats) - 1 + ) { + if (2 == \count($format)) { + return $format[1]; + } + + return floor($secs / $format[2]).' '.$format[1]; + } + } + } + } + + public static function formatMemory($memory) + { + if ($memory >= 1024 * 1024 * 1024) { + return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024); + } + + if ($memory >= 1024 * 1024) { + return sprintf('%.1f MiB', $memory / 1024 / 1024); + } + + if ($memory >= 1024) { + return sprintf('%d KiB', $memory / 1024); + } + + return sprintf('%d B', $memory); + } + + public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string) + { + return self::strlen(self::removeDecoration($formatter, $string)); + } + + public static function removeDecoration(OutputFormatterInterface $formatter, $string) + { + $isDecorated = $formatter->isDecorated(); + $formatter->setDecorated(false); + // remove <...> formatting + $string = $formatter->format($string); + // remove already formatted characters + $string = preg_replace("/\033\[[^m]*m/", '', $string); + $formatter->setDecorated($isDecorated); + + return $string; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/HelperInterface.php b/www/multitube/vendor/symfony/console/Helper/HelperInterface.php new file mode 100644 index 0000000..1ce8235 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/HelperInterface.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * HelperInterface is the interface all helpers must implement. + * + * @author Fabien Potencier + */ +interface HelperInterface +{ + /** + * Sets the helper set associated with this helper. + */ + public function setHelperSet(HelperSet $helperSet = null); + + /** + * Gets the helper set associated with this helper. + * + * @return HelperSet A HelperSet instance + */ + public function getHelperSet(); + + /** + * Returns the canonical name of this helper. + * + * @return string The canonical name + */ + public function getName(); +} diff --git a/www/multitube/vendor/symfony/console/Helper/HelperSet.php b/www/multitube/vendor/symfony/console/Helper/HelperSet.php new file mode 100644 index 0000000..c73fecd --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/HelperSet.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * HelperSet represents a set of helpers to be used with a command. + * + * @author Fabien Potencier + */ +class HelperSet implements \IteratorAggregate +{ + /** + * @var Helper[] + */ + private $helpers = []; + private $command; + + /** + * @param Helper[] $helpers An array of helper + */ + public function __construct(array $helpers = []) + { + foreach ($helpers as $alias => $helper) { + $this->set($helper, \is_int($alias) ? null : $alias); + } + } + + /** + * Sets a helper. + * + * @param HelperInterface $helper The helper instance + * @param string $alias An alias + */ + public function set(HelperInterface $helper, $alias = null) + { + $this->helpers[$helper->getName()] = $helper; + if (null !== $alias) { + $this->helpers[$alias] = $helper; + } + + $helper->setHelperSet($this); + } + + /** + * Returns true if the helper if defined. + * + * @param string $name The helper name + * + * @return bool true if the helper is defined, false otherwise + */ + public function has($name) + { + return isset($this->helpers[$name]); + } + + /** + * Gets a helper value. + * + * @param string $name The helper name + * + * @return HelperInterface The helper instance + * + * @throws InvalidArgumentException if the helper is not defined + */ + public function get($name) + { + if (!$this->has($name)) { + throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name)); + } + + return $this->helpers[$name]; + } + + public function setCommand(Command $command = null) + { + $this->command = $command; + } + + /** + * Gets the command associated with this helper set. + * + * @return Command A Command instance + */ + public function getCommand() + { + return $this->command; + } + + /** + * @return Helper[] + */ + public function getIterator() + { + return new \ArrayIterator($this->helpers); + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/InputAwareHelper.php b/www/multitube/vendor/symfony/console/Helper/InputAwareHelper.php new file mode 100644 index 0000000..0d0dba2 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/InputAwareHelper.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Input\InputAwareInterface; +use Symfony\Component\Console\Input\InputInterface; + +/** + * An implementation of InputAwareInterface for Helpers. + * + * @author Wouter J + */ +abstract class InputAwareHelper extends Helper implements InputAwareInterface +{ + protected $input; + + /** + * {@inheritdoc} + */ + public function setInput(InputInterface $input) + { + $this->input = $input; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/ProcessHelper.php b/www/multitube/vendor/symfony/console/Helper/ProcessHelper.php new file mode 100644 index 0000000..6cafb1f --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/ProcessHelper.php @@ -0,0 +1,145 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Process\Exception\ProcessFailedException; +use Symfony\Component\Process\Process; + +/** + * The ProcessHelper class provides helpers to run external processes. + * + * @author Fabien Potencier + */ +class ProcessHelper extends Helper +{ + /** + * Runs an external process. + * + * @param OutputInterface $output An OutputInterface instance + * @param string|array|Process $cmd An instance of Process or an array of arguments to escape and run or a command to run + * @param string|null $error An error message that must be displayed if something went wrong + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * @param int $verbosity The threshold for verbosity + * + * @return Process The process that ran + */ + public function run(OutputInterface $output, $cmd, $error = null, callable $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) + { + if (!class_exists(Process::class)) { + throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".'); + } + + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + if ($cmd instanceof Process) { + $process = $cmd; + } else { + $process = new Process($cmd); + } + + if ($verbosity <= $output->getVerbosity()) { + $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine()))); + } + + if ($output->isDebug()) { + $callback = $this->wrapCallback($output, $process, $callback); + } + + $process->run($callback); + + if ($verbosity <= $output->getVerbosity()) { + $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode()); + $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful())); + } + + if (!$process->isSuccessful() && null !== $error) { + $output->writeln(sprintf('%s', $this->escapeString($error))); + } + + return $process; + } + + /** + * Runs the process. + * + * This is identical to run() except that an exception is thrown if the process + * exits with a non-zero exit code. + * + * @param OutputInterface $output An OutputInterface instance + * @param string|Process $cmd An instance of Process or a command to run + * @param string|null $error An error message that must be displayed if something went wrong + * @param callable|null $callback A PHP callback to run whenever there is some + * output available on STDOUT or STDERR + * + * @return Process The process that ran + * + * @throws ProcessFailedException + * + * @see run() + */ + public function mustRun(OutputInterface $output, $cmd, $error = null, callable $callback = null) + { + $process = $this->run($output, $cmd, $error, $callback); + + if (!$process->isSuccessful()) { + throw new ProcessFailedException($process); + } + + return $process; + } + + /** + * Wraps a Process callback to add debugging output. + * + * @param OutputInterface $output An OutputInterface interface + * @param Process $process The Process + * @param callable|null $callback A PHP callable + * + * @return callable + */ + public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $formatter = $this->getHelperSet()->get('debug_formatter'); + + return function ($type, $buffer) use ($output, $process, $callback, $formatter) { + $output->write($formatter->progress(spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type)); + + if (null !== $callback) { + \call_user_func($callback, $type, $buffer); + } + }; + } + + private function escapeString($str) + { + return str_replace('<', '\\<', $str); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'process'; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/ProgressBar.php b/www/multitube/vendor/symfony/console/Helper/ProgressBar.php new file mode 100644 index 0000000..4ee4912 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/ProgressBar.php @@ -0,0 +1,614 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Terminal; + +/** + * The ProgressBar provides helpers to display progress output. + * + * @author Fabien Potencier + * @author Chris Jones + */ +final class ProgressBar +{ + private $barWidth = 28; + private $barChar; + private $emptyBarChar = '-'; + private $progressChar = '>'; + private $format; + private $internalFormat; + private $redrawFreq = 1; + private $output; + private $step = 0; + private $max; + private $startTime; + private $stepWidth; + private $percent = 0.0; + private $formatLineCount; + private $messages = []; + private $overwrite = true; + private $terminal; + private $firstRun = true; + + private static $formatters; + private static $formats; + + /** + * @param OutputInterface $output An OutputInterface instance + * @param int $max Maximum steps (0 if unknown) + */ + public function __construct(OutputInterface $output, $max = 0) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + $this->output = $output; + $this->setMaxSteps($max); + $this->terminal = new Terminal(); + + if (!$this->output->isDecorated()) { + // disable overwrite when output does not support ANSI codes. + $this->overwrite = false; + + // set a reasonable redraw frequency so output isn't flooded + $this->setRedrawFrequency($max / 10); + } + + $this->startTime = time(); + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + * + * @param string $name The placeholder name (including the delimiter char like %) + * @param callable $callable A PHP callable + */ + public static function setPlaceholderFormatterDefinition($name, callable $callable) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name. + * + * @param string $name The placeholder name (including the delimiter char like %) + * + * @return callable|null A PHP callable + */ + public static function getPlaceholderFormatterDefinition($name) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + } + + /** + * Sets a format for a given name. + * + * This method also allow you to override an existing format. + * + * @param string $name The format name + * @param string $format A format string + */ + public static function setFormatDefinition($name, $format) + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + self::$formats[$name] = $format; + } + + /** + * Gets the format for a given name. + * + * @param string $name The format name + * + * @return string|null A format string + */ + public static function getFormatDefinition($name) + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + return isset(self::$formats[$name]) ? self::$formats[$name] : null; + } + + /** + * Associates a text with a named placeholder. + * + * The text is displayed when the progress bar is rendered but only + * when the corresponding placeholder is part of the custom format line + * (by wrapping the name with %). + * + * @param string $message The text to associate with the placeholder + * @param string $name The name of the placeholder + */ + public function setMessage($message, $name = 'message') + { + $this->messages[$name] = $message; + } + + public function getMessage($name = 'message') + { + return $this->messages[$name]; + } + + /** + * Gets the progress bar start time. + * + * @return int The progress bar start time + */ + public function getStartTime() + { + return $this->startTime; + } + + /** + * Gets the progress bar maximal steps. + * + * @return int The progress bar max steps + */ + public function getMaxSteps() + { + return $this->max; + } + + /** + * Gets the current step position. + * + * @return int The progress bar step + */ + public function getProgress() + { + return $this->step; + } + + /** + * Gets the progress bar step width. + * + * @return int The progress bar step width + */ + private function getStepWidth() + { + return $this->stepWidth; + } + + /** + * Gets the current progress bar percent. + * + * @return float The current progress bar percent + */ + public function getProgressPercent() + { + return $this->percent; + } + + /** + * Sets the progress bar width. + * + * @param int $size The progress bar size + */ + public function setBarWidth($size) + { + $this->barWidth = max(1, (int) $size); + } + + /** + * Gets the progress bar width. + * + * @return int The progress bar size + */ + public function getBarWidth() + { + return $this->barWidth; + } + + /** + * Sets the bar character. + * + * @param string $char A character + */ + public function setBarCharacter($char) + { + $this->barChar = $char; + } + + /** + * Gets the bar character. + * + * @return string A character + */ + public function getBarCharacter() + { + if (null === $this->barChar) { + return $this->max ? '=' : $this->emptyBarChar; + } + + return $this->barChar; + } + + /** + * Sets the empty bar character. + * + * @param string $char A character + */ + public function setEmptyBarCharacter($char) + { + $this->emptyBarChar = $char; + } + + /** + * Gets the empty bar character. + * + * @return string A character + */ + public function getEmptyBarCharacter() + { + return $this->emptyBarChar; + } + + /** + * Sets the progress bar character. + * + * @param string $char A character + */ + public function setProgressCharacter($char) + { + $this->progressChar = $char; + } + + /** + * Gets the progress bar character. + * + * @return string A character + */ + public function getProgressCharacter() + { + return $this->progressChar; + } + + /** + * Sets the progress bar format. + * + * @param string $format The format + */ + public function setFormat($format) + { + $this->format = null; + $this->internalFormat = $format; + } + + /** + * Sets the redraw frequency. + * + * @param int|float $freq The frequency in steps + */ + public function setRedrawFrequency($freq) + { + $this->redrawFreq = max((int) $freq, 1); + } + + /** + * Starts the progress output. + * + * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged + */ + public function start($max = null) + { + $this->startTime = time(); + $this->step = 0; + $this->percent = 0.0; + + if (null !== $max) { + $this->setMaxSteps($max); + } + + $this->display(); + } + + /** + * Advances the progress output X steps. + * + * @param int $step Number of steps to advance + */ + public function advance($step = 1) + { + $this->setProgress($this->step + $step); + } + + /** + * Sets whether to overwrite the progressbar, false for new line. + * + * @param bool $overwrite + */ + public function setOverwrite($overwrite) + { + $this->overwrite = (bool) $overwrite; + } + + /** + * Sets the current progress. + * + * @param int $step The current progress + */ + public function setProgress($step) + { + $step = (int) $step; + + if ($this->max && $step > $this->max) { + $this->max = $step; + } elseif ($step < 0) { + $step = 0; + } + + $prevPeriod = (int) ($this->step / $this->redrawFreq); + $currPeriod = (int) ($step / $this->redrawFreq); + $this->step = $step; + $this->percent = $this->max ? (float) $this->step / $this->max : 0; + if ($prevPeriod !== $currPeriod || $this->max === $step) { + $this->display(); + } + } + + /** + * Finishes the progress output. + */ + public function finish() + { + if (!$this->max) { + $this->max = $this->step; + } + + if ($this->step === $this->max && !$this->overwrite) { + // prevent double 100% output + return; + } + + $this->setProgress($this->max); + } + + /** + * Outputs the current progress string. + */ + public function display() + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite($this->buildLine()); + } + + /** + * Removes the progress bar from the current line. + * + * This is useful if you wish to write some output + * while a progress bar is running. + * Call display() to show the progress bar again. + */ + public function clear() + { + if (!$this->overwrite) { + return; + } + + if (null === $this->format) { + $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat()); + } + + $this->overwrite(''); + } + + /** + * Sets the progress bar format. + * + * @param string $format The format + */ + private function setRealFormat($format) + { + // try to use the _nomax variant if available + if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { + $this->format = self::getFormatDefinition($format.'_nomax'); + } elseif (null !== self::getFormatDefinition($format)) { + $this->format = self::getFormatDefinition($format); + } else { + $this->format = $format; + } + + $this->formatLineCount = substr_count($this->format, "\n"); + } + + /** + * Sets the progress bar maximal steps. + * + * @param int $max The progress bar max steps + */ + private function setMaxSteps($max) + { + $this->max = max(0, (int) $max); + $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4; + } + + /** + * Overwrites a previous message to the output. + * + * @param string $message The message + */ + private function overwrite($message) + { + if ($this->overwrite) { + if (!$this->firstRun) { + // Erase previous lines + if ($this->formatLineCount > 0) { + $message = str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount).$message; + } + + // Move the cursor to the beginning of the line and erase the line + $message = "\x0D\x1B[2K$message"; + } + } elseif ($this->step > 0) { + $message = \PHP_EOL.$message; + } + + $this->firstRun = false; + + $this->output->write($message); + } + + private function determineBestFormat() + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->max ? 'verbose' : 'verbose_nomax'; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + return $this->max ? 'very_verbose' : 'very_verbose_nomax'; + case OutputInterface::VERBOSITY_DEBUG: + return $this->max ? 'debug' : 'debug_nomax'; + default: + return $this->max ? 'normal' : 'normal_nomax'; + } + } + + private static function initPlaceholderFormatters() + { + return [ + 'bar' => function (self $bar, OutputInterface $output) { + $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth()); + $display = str_repeat($bar->getBarCharacter(), $completeBars); + if ($completeBars < $bar->getBarWidth()) { + $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter()); + $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars); + } + + return $display; + }, + 'elapsed' => function (self $bar) { + return Helper::formatTime(time() - $bar->getStartTime()); + }, + 'remaining' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.'); + } + + if (!$bar->getProgress()) { + $remaining = 0; + } else { + $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress())); + } + + return Helper::formatTime($remaining); + }, + 'estimated' => function (self $bar) { + if (!$bar->getMaxSteps()) { + throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.'); + } + + if (!$bar->getProgress()) { + $estimated = 0; + } else { + $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps()); + } + + return Helper::formatTime($estimated); + }, + 'memory' => function (self $bar) { + return Helper::formatMemory(memory_get_usage(true)); + }, + 'current' => function (self $bar) { + return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT); + }, + 'max' => function (self $bar) { + return $bar->getMaxSteps(); + }, + 'percent' => function (self $bar) { + return floor($bar->getProgressPercent() * 100); + }, + ]; + } + + private static function initFormats() + { + return [ + 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', + 'normal_nomax' => ' %current% [%bar%]', + + 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', + 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + + 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', + 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%', + + 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', + 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%', + ]; + } + + /** + * @return string + */ + private function buildLine() + { + $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; + $callback = function ($matches) { + if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) { + $text = \call_user_func($formatter, $this, $this->output); + } elseif (isset($this->messages[$matches[1]])) { + $text = $this->messages[$matches[1]]; + } else { + return $matches[0]; + } + + if (isset($matches[2])) { + $text = sprintf('%'.$matches[2], $text); + } + + return $text; + }; + $line = preg_replace_callback($regex, $callback, $this->format); + + // gets string length for each sub line with multiline format + $linesLength = array_map(function ($subLine) { + return Helper::strlenWithoutDecoration($this->output->getFormatter(), rtrim($subLine, "\r")); + }, explode("\n", $line)); + + $linesWidth = max($linesLength); + + $terminalWidth = $this->terminal->getWidth(); + if ($linesWidth <= $terminalWidth) { + return $line; + } + + $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth); + + return preg_replace_callback($regex, $callback, $this->format); + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/ProgressIndicator.php b/www/multitube/vendor/symfony/console/Helper/ProgressIndicator.php new file mode 100644 index 0000000..60ca021 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/ProgressIndicator.php @@ -0,0 +1,270 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * @author Kevin Bond + */ +class ProgressIndicator +{ + private $output; + private $startTime; + private $format; + private $message; + private $indicatorValues; + private $indicatorCurrent; + private $indicatorChangeInterval; + private $indicatorUpdateTime; + private $started = false; + + private static $formatters; + private static $formats; + + /** + * @param string|null $format Indicator format + * @param int $indicatorChangeInterval Change interval in milliseconds + * @param array|null $indicatorValues Animated indicator characters + */ + public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null) + { + $this->output = $output; + + if (null === $format) { + $format = $this->determineBestFormat(); + } + + if (null === $indicatorValues) { + $indicatorValues = ['-', '\\', '|', '/']; + } + + $indicatorValues = array_values($indicatorValues); + + if (2 > \count($indicatorValues)) { + throw new InvalidArgumentException('Must have at least 2 indicator value characters.'); + } + + $this->format = self::getFormatDefinition($format); + $this->indicatorChangeInterval = $indicatorChangeInterval; + $this->indicatorValues = $indicatorValues; + $this->startTime = time(); + } + + /** + * Sets the current indicator message. + * + * @param string|null $message + */ + public function setMessage($message) + { + $this->message = $message; + + $this->display(); + } + + /** + * Starts the indicator output. + * + * @param $message + */ + public function start($message) + { + if ($this->started) { + throw new LogicException('Progress indicator already started.'); + } + + $this->message = $message; + $this->started = true; + $this->startTime = time(); + $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval; + $this->indicatorCurrent = 0; + + $this->display(); + } + + /** + * Advances the indicator. + */ + public function advance() + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + if (!$this->output->isDecorated()) { + return; + } + + $currentTime = $this->getCurrentTimeInMilliseconds(); + + if ($currentTime < $this->indicatorUpdateTime) { + return; + } + + $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval; + ++$this->indicatorCurrent; + + $this->display(); + } + + /** + * Finish the indicator with message. + * + * @param $message + */ + public function finish($message) + { + if (!$this->started) { + throw new LogicException('Progress indicator has not yet been started.'); + } + + $this->message = $message; + $this->display(); + $this->output->writeln(''); + $this->started = false; + } + + /** + * Gets the format for a given name. + * + * @param string $name The format name + * + * @return string|null A format string + */ + public static function getFormatDefinition($name) + { + if (!self::$formats) { + self::$formats = self::initFormats(); + } + + return isset(self::$formats[$name]) ? self::$formats[$name] : null; + } + + /** + * Sets a placeholder formatter for a given name. + * + * This method also allow you to override an existing placeholder. + * + * @param string $name The placeholder name (including the delimiter char like %) + * @param callable $callable A PHP callable + */ + public static function setPlaceholderFormatterDefinition($name, $callable) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + self::$formatters[$name] = $callable; + } + + /** + * Gets the placeholder formatter for a given name. + * + * @param string $name The placeholder name (including the delimiter char like %) + * + * @return callable|null A PHP callable + */ + public static function getPlaceholderFormatterDefinition($name) + { + if (!self::$formatters) { + self::$formatters = self::initPlaceholderFormatters(); + } + + return isset(self::$formatters[$name]) ? self::$formatters[$name] : null; + } + + private function display() + { + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; + } + + $self = $this; + + $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) { + if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) { + return \call_user_func($formatter, $self); + } + + return $matches[0]; + }, $this->format)); + } + + private function determineBestFormat() + { + switch ($this->output->getVerbosity()) { + // OutputInterface::VERBOSITY_QUIET: display is disabled anyway + case OutputInterface::VERBOSITY_VERBOSE: + return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi'; + case OutputInterface::VERBOSITY_VERY_VERBOSE: + case OutputInterface::VERBOSITY_DEBUG: + return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi'; + default: + return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi'; + } + } + + /** + * Overwrites a previous message to the output. + * + * @param string $message The message + */ + private function overwrite($message) + { + if ($this->output->isDecorated()) { + $this->output->write("\x0D\x1B[2K"); + $this->output->write($message); + } else { + $this->output->writeln($message); + } + } + + private function getCurrentTimeInMilliseconds() + { + return round(microtime(true) * 1000); + } + + private static function initPlaceholderFormatters() + { + return [ + 'indicator' => function (self $indicator) { + return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)]; + }, + 'message' => function (self $indicator) { + return $indicator->message; + }, + 'elapsed' => function (self $indicator) { + return Helper::formatTime(time() - $indicator->startTime); + }, + 'memory' => function () { + return Helper::formatMemory(memory_get_usage(true)); + }, + ]; + } + + private static function initFormats() + { + return [ + 'normal' => ' %indicator% %message%', + 'normal_no_ansi' => ' %message%', + + 'verbose' => ' %indicator% %message% (%elapsed:6s%)', + 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', + + 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', + 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)', + ]; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/QuestionHelper.php b/www/multitube/vendor/symfony/console/Helper/QuestionHelper.php new file mode 100644 index 0000000..ac6f2be --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/QuestionHelper.php @@ -0,0 +1,518 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterStyle; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\StreamableInputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +/** + * The QuestionHelper class provides helpers to interact with the user. + * + * @author Fabien Potencier + */ +class QuestionHelper extends Helper +{ + private $inputStream; + private static $shell; + private static $stty = true; + + /** + * Asks a question to the user. + * + * @return mixed The user answer + * + * @throws RuntimeException If there is no data to read in the input stream + */ + public function ask(InputInterface $input, OutputInterface $output, Question $question) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + if (!$input->isInteractive()) { + $default = $question->getDefault(); + + if (null === $default) { + return $default; + } + + if ($validator = $question->getValidator()) { + return \call_user_func($question->getValidator(), $default); + } elseif ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + if (!$question->isMultiselect()) { + return isset($choices[$default]) ? $choices[$default] : $default; + } + + $default = explode(',', $default); + foreach ($default as $k => $v) { + $v = trim($v); + $default[$k] = isset($choices[$v]) ? $choices[$v] : $v; + } + } + + return $default; + } + + if ($input instanceof StreamableInputInterface && $stream = $input->getStream()) { + $this->inputStream = $stream; + } + + if (!$question->getValidator()) { + return $this->doAsk($output, $question); + } + + $interviewer = function () use ($output, $question) { + return $this->doAsk($output, $question); + }; + + return $this->validateAttempts($interviewer, $output, $question); + } + + /** + * Sets the input stream to read from when interacting with the user. + * + * This is mainly useful for testing purpose. + * + * @deprecated since version 3.2, to be removed in 4.0. Use + * StreamableInputInterface::setStream() instead. + * + * @param resource $stream The input stream + * + * @throws InvalidArgumentException In case the stream is not a resource + */ + public function setInputStream($stream) + { + @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), \E_USER_DEPRECATED); + + if (!\is_resource($stream)) { + throw new InvalidArgumentException('Input stream must be a valid resource.'); + } + + $this->inputStream = $stream; + } + + /** + * Returns the helper's input stream. + * + * @deprecated since version 3.2, to be removed in 4.0. Use + * StreamableInputInterface::getStream() instead. + * + * @return resource + */ + public function getInputStream() + { + if (0 === \func_num_args() || func_get_arg(0)) { + @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), \E_USER_DEPRECATED); + } + + return $this->inputStream; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'question'; + } + + /** + * Prevents usage of stty. + */ + public static function disableStty() + { + self::$stty = false; + } + + /** + * Asks the question to the user. + * + * @return bool|mixed|string|null + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function doAsk(OutputInterface $output, Question $question) + { + $this->writePrompt($output, $question); + + $inputStream = $this->inputStream ?: \STDIN; + $autocomplete = $question->getAutocompleterValues(); + + if (\function_exists('sapi_windows_cp_set')) { + // Codepage used by cmd.exe on Windows to allow special characters (éàüñ). + @sapi_windows_cp_set(1252); + } + + if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) { + $ret = false; + if ($question->isHidden()) { + try { + $ret = trim($this->getHiddenResponse($output, $inputStream)); + } catch (RuntimeException $e) { + if (!$question->isHiddenFallback()) { + throw $e; + } + } + } + + if (false === $ret) { + $ret = fgets($inputStream, 4096); + if (false === $ret) { + throw new RuntimeException('Aborted.'); + } + $ret = trim($ret); + } + } else { + $ret = trim($this->autocomplete($output, $question, $inputStream, \is_array($autocomplete) ? $autocomplete : iterator_to_array($autocomplete, false))); + } + + $ret = \strlen($ret) > 0 ? $ret : $question->getDefault(); + + if ($normalizer = $question->getNormalizer()) { + return $normalizer($ret); + } + + return $ret; + } + + /** + * Outputs the question prompt. + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $message = $question->getQuestion(); + + if ($question instanceof ChoiceQuestion) { + $output->writeln(array_merge([ + $question->getQuestion(), + ], $this->formatChoiceQuestionChoices($question, 'info'))); + + $message = $question->getPrompt(); + } + + $output->write($message); + } + + /** + * @param string $tag + * + * @return string[] + */ + protected function formatChoiceQuestionChoices(ChoiceQuestion $question, $tag) + { + $messages = []; + + $maxWidth = max(array_map('self::strlen', array_keys($choices = $question->getChoices()))); + + foreach ($choices as $key => $value) { + $padding = str_repeat(' ', $maxWidth - self::strlen($key)); + + $messages[] = sprintf(" [<$tag>%s$padding] %s", $key, $value); + } + + return $messages; + } + + /** + * Outputs an error message. + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) { + $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'); + } else { + $message = ''.$error->getMessage().''; + } + + $output->writeln($message); + } + + /** + * Autocompletes a question. + * + * @param resource $inputStream + * + * @return string + */ + private function autocomplete(OutputInterface $output, Question $question, $inputStream, array $autocomplete) + { + $fullChoice = ''; + $ret = ''; + + $i = 0; + $ofs = -1; + $matches = $autocomplete; + $numMatches = \count($matches); + + $sttyMode = shell_exec('stty -g'); + + // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead) + shell_exec('stty -icanon -echo'); + + // Add highlighted text style + $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white')); + + // Read a keypress + while (!feof($inputStream)) { + $c = fread($inputStream, 1); + + // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false. + if (false === $c || ('' === $ret && '' === $c && null === $question->getDefault())) { + shell_exec(sprintf('stty %s', $sttyMode)); + throw new RuntimeException('Aborted.'); + } elseif ("\177" === $c) { // Backspace Character + if (0 === $numMatches && 0 !== $i) { + --$i; + $fullChoice = self::substr($fullChoice, 0, $i); + // Move cursor backwards + $output->write("\033[1D"); + } + + if (0 === $i) { + $ofs = -1; + $matches = $autocomplete; + $numMatches = \count($matches); + } else { + $numMatches = 0; + } + + // Pop the last character off the end of our string + $ret = self::substr($ret, 0, $i); + } elseif ("\033" === $c) { + // Did we read an escape sequence? + $c .= fread($inputStream, 2); + + // A = Up Arrow. B = Down Arrow + if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) { + if ('A' === $c[2] && -1 === $ofs) { + $ofs = 0; + } + + if (0 === $numMatches) { + continue; + } + + $ofs += ('A' === $c[2]) ? -1 : 1; + $ofs = ($numMatches + $ofs) % $numMatches; + } + } elseif (\ord($c) < 32) { + if ("\t" === $c || "\n" === $c) { + if ($numMatches > 0 && -1 !== $ofs) { + $ret = $matches[$ofs]; + // Echo out remaining chars for current match + $remainingCharacters = substr($ret, \strlen(trim($this->mostRecentlyEnteredValue($fullChoice)))); + $output->write($remainingCharacters); + $fullChoice .= $remainingCharacters; + $i = self::strlen($fullChoice); + } + + if ("\n" === $c) { + $output->write($c); + break; + } + + $numMatches = 0; + } + + continue; + } else { + if ("\x80" <= $c) { + $c .= fread($inputStream, ["\xC0" => 1, "\xD0" => 1, "\xE0" => 2, "\xF0" => 3][$c & "\xF0"]); + } + + $output->write($c); + $ret .= $c; + $fullChoice .= $c; + ++$i; + + $tempRet = $ret; + + if ($question instanceof ChoiceQuestion && $question->isMultiselect()) { + $tempRet = $this->mostRecentlyEnteredValue($fullChoice); + } + + $numMatches = 0; + $ofs = 0; + + foreach ($autocomplete as $value) { + // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle) + if (0 === strpos($value, $tempRet)) { + $matches[$numMatches++] = $value; + } + } + } + + // Erase characters from cursor to end of line + $output->write("\033[K"); + + if ($numMatches > 0 && -1 !== $ofs) { + // Save cursor position + $output->write("\0337"); + // Write highlighted text, complete the partially entered response + $charactersEntered = \strlen(trim($this->mostRecentlyEnteredValue($fullChoice))); + $output->write(''.OutputFormatter::escapeTrailingBackslash(substr($matches[$ofs], $charactersEntered)).''); + // Restore cursor position + $output->write("\0338"); + } + } + + // Reset stty so it behaves normally again + shell_exec(sprintf('stty %s', $sttyMode)); + + return $fullChoice; + } + + private function mostRecentlyEnteredValue($entered) + { + // Determine the most recent value that the user entered + if (false === strpos($entered, ',')) { + return $entered; + } + + $choices = explode(',', $entered); + if (\strlen($lastChoice = trim($choices[\count($choices) - 1])) > 0) { + return $lastChoice; + } + + return $entered; + } + + /** + * Gets a hidden response from user. + * + * @param OutputInterface $output An Output instance + * @param resource $inputStream The handler resource + * + * @return string The answer + * + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden + */ + private function getHiddenResponse(OutputInterface $output, $inputStream) + { + if ('\\' === \DIRECTORY_SEPARATOR) { + $exe = __DIR__.'/../Resources/bin/hiddeninput.exe'; + + // handle code running from a phar + if ('phar:' === substr(__FILE__, 0, 5)) { + $tmpExe = sys_get_temp_dir().'/hiddeninput.exe'; + copy($exe, $tmpExe); + $exe = $tmpExe; + } + + $value = rtrim(shell_exec($exe)); + $output->writeln(''); + + if (isset($tmpExe)) { + unlink($tmpExe); + } + + return $value; + } + + if (self::$stty && Terminal::hasSttyAvailable()) { + $sttyMode = shell_exec('stty -g'); + + shell_exec('stty -echo'); + $value = fgets($inputStream, 4096); + shell_exec(sprintf('stty %s', $sttyMode)); + + if (false === $value) { + throw new RuntimeException('Aborted.'); + } + + $value = trim($value); + $output->writeln(''); + + return $value; + } + + if (false !== $shell = $this->getShell()) { + $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; + $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); + $value = rtrim(shell_exec($command)); + $output->writeln(''); + + return $value; + } + + throw new RuntimeException('Unable to hide the response.'); + } + + /** + * Validates an attempt. + * + * @param callable $interviewer A callable that will ask for a question and return the result + * @param OutputInterface $output An Output instance + * @param Question $question A Question instance + * + * @return mixed The validated response + * + * @throws \Exception In case the max number of attempts has been reached and no valid response has been given + */ + private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question) + { + $error = null; + $attempts = $question->getMaxAttempts(); + while (null === $attempts || $attempts--) { + if (null !== $error) { + $this->writeError($output, $error); + } + + try { + return \call_user_func($question->getValidator(), $interviewer()); + } catch (RuntimeException $e) { + throw $e; + } catch (\Exception $error) { + } + } + + throw $error; + } + + /** + * Returns a valid unix shell. + * + * @return string|bool The valid shell name, false in case no valid shell is found + */ + private function getShell() + { + if (null !== self::$shell) { + return self::$shell; + } + + self::$shell = false; + + if (file_exists('/usr/bin/env')) { + // handle other OSs with bash/zsh/ksh/csh if available to hide the answer + $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null"; + foreach (['bash', 'zsh', 'ksh', 'csh'] as $sh) { + if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) { + self::$shell = $sh; + break; + } + } + } + + return self::$shell; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/SymfonyQuestionHelper.php b/www/multitube/vendor/symfony/console/Helper/SymfonyQuestionHelper.php new file mode 100644 index 0000000..86bebd9 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/SymfonyQuestionHelper.php @@ -0,0 +1,124 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\LogicException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Symfony Style Guide compliant question helper. + * + * @author Kevin Bond + */ +class SymfonyQuestionHelper extends QuestionHelper +{ + /** + * {@inheritdoc} + * + * To be removed in 4.0 + */ + public function ask(InputInterface $input, OutputInterface $output, Question $question) + { + $validator = $question->getValidator(); + $question->setValidator(function ($value) use ($validator) { + if (null !== $validator) { + $value = $validator($value); + } else { + // make required + if (!\is_array($value) && !\is_bool($value) && 0 === \strlen($value)) { + @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', \E_USER_DEPRECATED); + + throw new LogicException('A value is required.'); + } + } + + return $value; + }); + + return parent::ask($input, $output, $question); + } + + /** + * {@inheritdoc} + */ + protected function writePrompt(OutputInterface $output, Question $question) + { + $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion()); + $default = $question->getDefault(); + + switch (true) { + case null === $default: + $text = sprintf(' %s:', $text); + + break; + + case $question instanceof ConfirmationQuestion: + $text = sprintf(' %s (yes/no) [%s]:', $text, $default ? 'yes' : 'no'); + + break; + + case $question instanceof ChoiceQuestion && $question->isMultiselect(): + $choices = $question->getChoices(); + $default = explode(',', $default); + + foreach ($default as $key => $value) { + $default[$key] = $choices[trim($value)]; + } + + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(implode(', ', $default))); + + break; + + case $question instanceof ChoiceQuestion: + $choices = $question->getChoices(); + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape(isset($choices[$default]) ? $choices[$default] : $default)); + + break; + + default: + $text = sprintf(' %s [%s]:', $text, OutputFormatter::escape($default)); + } + + $output->writeln($text); + + $prompt = ' > '; + + if ($question instanceof ChoiceQuestion) { + $output->writeln($this->formatChoiceQuestionChoices($question, 'comment')); + + $prompt = $question->getPrompt(); + } + + $output->write($prompt); + } + + /** + * {@inheritdoc} + */ + protected function writeError(OutputInterface $output, \Exception $error) + { + if ($output instanceof SymfonyStyle) { + $output->newLine(); + $output->error($error->getMessage()); + + return; + } + + parent::writeError($output, $error); + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/Table.php b/www/multitube/vendor/symfony/console/Helper/Table.php new file mode 100644 index 0000000..e6dc6a8 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/Table.php @@ -0,0 +1,698 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Provides helpers to display a table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + * @author Abdellatif Ait boudad + * @author Max Grigorian + */ +class Table +{ + /** + * Table headers. + */ + private $headers = []; + + /** + * Table rows. + */ + private $rows = []; + + /** + * Column widths cache. + */ + private $effectiveColumnWidths = []; + + /** + * Number of columns cache. + * + * @var int + */ + private $numberOfColumns; + + /** + * @var OutputInterface + */ + private $output; + + /** + * @var TableStyle + */ + private $style; + + /** + * @var array + */ + private $columnStyles = []; + + /** + * User set column widths. + * + * @var array + */ + private $columnWidths = []; + + private static $styles; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + $this->setStyle('default'); + } + + /** + * Sets a style definition. + * + * @param string $name The style name + * @param TableStyle $style A TableStyle instance + */ + public static function setStyleDefinition($name, TableStyle $style) + { + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + self::$styles[$name] = $style; + } + + /** + * Gets a style definition by name. + * + * @param string $name The style name + * + * @return TableStyle + */ + public static function getStyleDefinition($name) + { + if (!self::$styles) { + self::$styles = self::initStyles(); + } + + if (isset(self::$styles[$name])) { + return self::$styles[$name]; + } + + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } + + /** + * Sets table style. + * + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setStyle($name) + { + $this->style = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current table style. + * + * @return TableStyle + */ + public function getStyle() + { + return $this->style; + } + + /** + * Sets table column style. + * + * @param int $columnIndex Column index + * @param TableStyle|string $name The style name or a TableStyle instance + * + * @return $this + */ + public function setColumnStyle($columnIndex, $name) + { + $columnIndex = (int) $columnIndex; + + $this->columnStyles[$columnIndex] = $this->resolveStyle($name); + + return $this; + } + + /** + * Gets the current style for a column. + * + * If style was not set, it returns the global table style. + * + * @param int $columnIndex Column index + * + * @return TableStyle + */ + public function getColumnStyle($columnIndex) + { + if (isset($this->columnStyles[$columnIndex])) { + return $this->columnStyles[$columnIndex]; + } + + return $this->getStyle(); + } + + /** + * Sets the minimum width of a column. + * + * @param int $columnIndex Column index + * @param int $width Minimum column width in characters + * + * @return $this + */ + public function setColumnWidth($columnIndex, $width) + { + $this->columnWidths[(int) $columnIndex] = (int) $width; + + return $this; + } + + /** + * Sets the minimum width of all columns. + * + * @return $this + */ + public function setColumnWidths(array $widths) + { + $this->columnWidths = []; + foreach ($widths as $index => $width) { + $this->setColumnWidth($index, $width); + } + + return $this; + } + + public function setHeaders(array $headers) + { + $headers = array_values($headers); + if (!empty($headers) && !\is_array($headers[0])) { + $headers = [$headers]; + } + + $this->headers = $headers; + + return $this; + } + + public function setRows(array $rows) + { + $this->rows = []; + + return $this->addRows($rows); + } + + public function addRows(array $rows) + { + foreach ($rows as $row) { + $this->addRow($row); + } + + return $this; + } + + public function addRow($row) + { + if ($row instanceof TableSeparator) { + $this->rows[] = $row; + + return $this; + } + + if (!\is_array($row)) { + throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.'); + } + + $this->rows[] = array_values($row); + + return $this; + } + + public function setRow($column, array $row) + { + $this->rows[$column] = $row; + + return $this; + } + + /** + * Renders table to output. + * + * Example: + * + * +---------------+-----------------------+------------------+ + * | ISBN | Title | Author | + * +---------------+-----------------------+------------------+ + * | 99921-58-10-7 | Divine Comedy | Dante Alighieri | + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien | + * +---------------+-----------------------+------------------+ + */ + public function render() + { + $this->calculateNumberOfColumns(); + $rows = $this->buildTableRows($this->rows); + $headers = $this->buildTableRows($this->headers); + + $this->calculateColumnsWidth(array_merge($headers, $rows)); + + $this->renderRowSeparator(); + if (!empty($headers)) { + foreach ($headers as $header) { + $this->renderRow($header, $this->style->getCellHeaderFormat()); + $this->renderRowSeparator(); + } + } + foreach ($rows as $row) { + if ($row instanceof TableSeparator) { + $this->renderRowSeparator(); + } else { + $this->renderRow($row, $this->style->getCellRowFormat()); + } + } + if (!empty($rows)) { + $this->renderRowSeparator(); + } + + $this->cleanup(); + } + + /** + * Renders horizontal header separator. + * + * Example: + * + * +-----+-----------+-------+ + */ + private function renderRowSeparator() + { + if (0 === $count = $this->numberOfColumns) { + return; + } + + if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) { + return; + } + + $markup = $this->style->getCrossingChar(); + for ($column = 0; $column < $count; ++$column) { + $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->effectiveColumnWidths[$column]).$this->style->getCrossingChar(); + } + + $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup)); + } + + /** + * Renders vertical column separator. + */ + private function renderColumnSeparator() + { + return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()); + } + + /** + * Renders table row. + * + * Example: + * + * | 9971-5-0210-0 | A Tale of Two Cities | Charles Dickens | + * + * @param string $cellFormat + */ + private function renderRow(array $row, $cellFormat) + { + if (empty($row)) { + return; + } + + $rowContent = $this->renderColumnSeparator(); + foreach ($this->getRowColumns($row) as $column) { + $rowContent .= $this->renderCell($row, $column, $cellFormat); + $rowContent .= $this->renderColumnSeparator(); + } + $this->output->writeln($rowContent); + } + + /** + * Renders table cell with padding. + * + * @param int $column + * @param string $cellFormat + */ + private function renderCell(array $row, $column, $cellFormat) + { + $cell = isset($row[$column]) ? $row[$column] : ''; + $width = $this->effectiveColumnWidths[$column]; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // add the width of the following columns(numbers of colspan). + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) { + $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn]; + } + } + + // str_pad won't work properly with multi-byte strings, we need to fix the padding + if (false !== $encoding = mb_detect_encoding($cell, null, true)) { + $width += \strlen($cell) - mb_strwidth($cell, $encoding); + } + + $style = $this->getColumnStyle($column); + + if ($cell instanceof TableSeparator) { + return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width)); + } + + $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + $content = sprintf($style->getCellRowContentFormat(), $cell); + + return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())); + } + + /** + * Calculate number of columns for this table. + */ + private function calculateNumberOfColumns() + { + if (null !== $this->numberOfColumns) { + return; + } + + $columns = [0]; + foreach (array_merge($this->headers, $this->rows) as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + $columns[] = $this->getNumberOfColumns($row); + } + + $this->numberOfColumns = max($columns); + } + + private function buildTableRows($rows) + { + $unmergedRows = []; + for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) { + $rows = $this->fillNextRows($rows, $rowKey); + + // Remove any new line breaks and replace it with a new line + foreach ($rows[$rowKey] as $column => $cell) { + if (!strstr($cell, "\n")) { + continue; + } + $lines = explode("\n", str_replace("\n", "\n", $cell)); + foreach ($lines as $lineKey => $line) { + if ($cell instanceof TableCell) { + $line = new TableCell($line, ['colspan' => $cell->getColspan()]); + } + if (0 === $lineKey) { + $rows[$rowKey][$column] = $line; + } else { + $unmergedRows[$rowKey][$lineKey][$column] = $line; + } + } + } + } + + $tableRows = []; + foreach ($rows as $rowKey => $row) { + $tableRows[] = $this->fillCells($row); + if (isset($unmergedRows[$rowKey])) { + $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]); + } + } + + return $tableRows; + } + + /** + * fill rows that contains rowspan > 1. + * + * @param int $line + * + * @return array + * + * @throws InvalidArgumentException + */ + private function fillNextRows(array $rows, $line) + { + $unmergedRows = []; + foreach ($rows[$line] as $column => $cell) { + if (null !== $cell && !$cell instanceof TableCell && !is_scalar($cell) && !(\is_object($cell) && method_exists($cell, '__toString'))) { + throw new InvalidArgumentException(sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \gettype($cell))); + } + if ($cell instanceof TableCell && $cell->getRowspan() > 1) { + $nbLines = $cell->getRowspan() - 1; + $lines = [$cell]; + if (strstr($cell, "\n")) { + $lines = explode("\n", str_replace("\n", "\n", $cell)); + $nbLines = \count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines; + + $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan()]); + unset($lines[0]); + } + + // create a two dimensional array (rowspan x colspan) + $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, []), $unmergedRows); + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; + $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan()]); + if ($nbLines === $unmergedRowKey - $line) { + break; + } + } + } + } + + foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { + // we need to know if $unmergedRow will be merged or inserted into $rows + if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) { + foreach ($unmergedRow as $cellKey => $cell) { + // insert cell into row at cellKey position + array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]); + } + } else { + $row = $this->copyRow($rows, $unmergedRowKey - 1); + foreach ($unmergedRow as $column => $cell) { + if (!empty($cell)) { + $row[$column] = $unmergedRow[$column]; + } + } + array_splice($rows, $unmergedRowKey, 0, [$row]); + } + } + + return $rows; + } + + /** + * fill cells for a row that contains colspan > 1. + * + * @return array + */ + private function fillCells($row) + { + $newRow = []; + foreach ($row as $column => $cell) { + $newRow[] = $cell; + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) { + // insert empty value at column position + $newRow[] = ''; + } + } + } + + return $newRow ?: $row; + } + + /** + * @param int $line + * + * @return array + */ + private function copyRow(array $rows, $line) + { + $row = $rows[$line]; + foreach ($row as $cellKey => $cellValue) { + $row[$cellKey] = ''; + if ($cellValue instanceof TableCell) { + $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]); + } + } + + return $row; + } + + /** + * Gets number of columns by row. + * + * @return int + */ + private function getNumberOfColumns(array $row) + { + $columns = \count($row); + foreach ($row as $column) { + $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0; + } + + return $columns; + } + + /** + * Gets list of columns for the given row. + * + * @return array + */ + private function getRowColumns(array $row) + { + $columns = range(0, $this->numberOfColumns - 1); + foreach ($row as $cellKey => $cell) { + if ($cell instanceof TableCell && $cell->getColspan() > 1) { + // exclude grouped columns. + $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1)); + } + } + + return $columns; + } + + /** + * Calculates columns widths. + */ + private function calculateColumnsWidth(array $rows) + { + for ($column = 0; $column < $this->numberOfColumns; ++$column) { + $lengths = []; + foreach ($rows as $row) { + if ($row instanceof TableSeparator) { + continue; + } + + foreach ($row as $i => $cell) { + if ($cell instanceof TableCell) { + $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell); + $textLength = Helper::strlen($textContent); + if ($textLength > 0) { + $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan())); + foreach ($contentColumns as $position => $content) { + $row[$i + $position] = $content; + } + } + } + } + + $lengths[] = $this->getCellWidth($row, $column); + } + + $this->effectiveColumnWidths[$column] = max($lengths) + Helper::strlen($this->style->getCellRowContentFormat()) - 2; + } + } + + /** + * Gets column width. + * + * @return int + */ + private function getColumnSeparatorWidth() + { + return Helper::strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar())); + } + + /** + * Gets cell width. + * + * @param int $column + * + * @return int + */ + private function getCellWidth(array $row, $column) + { + $cellWidth = 0; + + if (isset($row[$column])) { + $cell = $row[$column]; + $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell); + } + + $columnWidth = isset($this->columnWidths[$column]) ? $this->columnWidths[$column] : 0; + + return max($cellWidth, $columnWidth); + } + + /** + * Called after rendering to cleanup cache data. + */ + private function cleanup() + { + $this->effectiveColumnWidths = []; + $this->numberOfColumns = null; + } + + private static function initStyles() + { + $borderless = new TableStyle(); + $borderless + ->setHorizontalBorderChar('=') + ->setVerticalBorderChar(' ') + ->setCrossingChar(' ') + ; + + $compact = new TableStyle(); + $compact + ->setHorizontalBorderChar('') + ->setVerticalBorderChar(' ') + ->setCrossingChar('') + ->setCellRowContentFormat('%s') + ; + + $styleGuide = new TableStyle(); + $styleGuide + ->setHorizontalBorderChar('-') + ->setVerticalBorderChar(' ') + ->setCrossingChar(' ') + ->setCellHeaderFormat('%s') + ; + + return [ + 'default' => new TableStyle(), + 'borderless' => $borderless, + 'compact' => $compact, + 'symfony-style-guide' => $styleGuide, + ]; + } + + private function resolveStyle($name) + { + if ($name instanceof TableStyle) { + return $name; + } + + if (isset(self::$styles[$name])) { + return self::$styles[$name]; + } + + throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name)); + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/TableCell.php b/www/multitube/vendor/symfony/console/Helper/TableCell.php new file mode 100644 index 0000000..78e5d69 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/TableCell.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * @author Abdellatif Ait boudad + */ +class TableCell +{ + private $value; + private $options = [ + 'rowspan' => 1, + 'colspan' => 1, + ]; + + /** + * @param string $value + */ + public function __construct($value = '', array $options = []) + { + if (is_numeric($value) && !\is_string($value)) { + $value = (string) $value; + } + + $this->value = $value; + + // check option names + if ($diff = array_diff(array_keys($options), array_keys($this->options))) { + throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff))); + } + + $this->options = array_merge($this->options, $options); + } + + /** + * Returns the cell value. + * + * @return string + */ + public function __toString() + { + return $this->value; + } + + /** + * Gets number of colspan. + * + * @return int + */ + public function getColspan() + { + return (int) $this->options['colspan']; + } + + /** + * Gets number of rowspan. + * + * @return int + */ + public function getRowspan() + { + return (int) $this->options['rowspan']; + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/TableSeparator.php b/www/multitube/vendor/symfony/console/Helper/TableSeparator.php new file mode 100644 index 0000000..e541c53 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/TableSeparator.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +/** + * Marks a row as being a separator. + * + * @author Fabien Potencier + */ +class TableSeparator extends TableCell +{ + public function __construct(array $options = []) + { + parent::__construct('', $options); + } +} diff --git a/www/multitube/vendor/symfony/console/Helper/TableStyle.php b/www/multitube/vendor/symfony/console/Helper/TableStyle.php new file mode 100644 index 0000000..98d8847 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Helper/TableStyle.php @@ -0,0 +1,258 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Helper; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Defines the styles for a Table. + * + * @author Fabien Potencier + * @author Саша Стаменковић + */ +class TableStyle +{ + private $paddingChar = ' '; + private $horizontalBorderChar = '-'; + private $verticalBorderChar = '|'; + private $crossingChar = '+'; + private $cellHeaderFormat = '%s'; + private $cellRowFormat = '%s'; + private $cellRowContentFormat = ' %s '; + private $borderFormat = '%s'; + private $padType = \STR_PAD_RIGHT; + + /** + * Sets padding character, used for cell padding. + * + * @param string $paddingChar + * + * @return $this + */ + public function setPaddingChar($paddingChar) + { + if (!$paddingChar) { + throw new LogicException('The padding char must not be empty.'); + } + + $this->paddingChar = $paddingChar; + + return $this; + } + + /** + * Gets padding character, used for cell padding. + * + * @return string + */ + public function getPaddingChar() + { + return $this->paddingChar; + } + + /** + * Sets horizontal border character. + * + * @param string $horizontalBorderChar + * + * @return $this + */ + public function setHorizontalBorderChar($horizontalBorderChar) + { + $this->horizontalBorderChar = $horizontalBorderChar; + + return $this; + } + + /** + * Gets horizontal border character. + * + * @return string + */ + public function getHorizontalBorderChar() + { + return $this->horizontalBorderChar; + } + + /** + * Sets vertical border character. + * + * @param string $verticalBorderChar + * + * @return $this + */ + public function setVerticalBorderChar($verticalBorderChar) + { + $this->verticalBorderChar = $verticalBorderChar; + + return $this; + } + + /** + * Gets vertical border character. + * + * @return string + */ + public function getVerticalBorderChar() + { + return $this->verticalBorderChar; + } + + /** + * Sets crossing character. + * + * @param string $crossingChar + * + * @return $this + */ + public function setCrossingChar($crossingChar) + { + $this->crossingChar = $crossingChar; + + return $this; + } + + /** + * Gets crossing character. + * + * @return string + */ + public function getCrossingChar() + { + return $this->crossingChar; + } + + /** + * Sets header cell format. + * + * @param string $cellHeaderFormat + * + * @return $this + */ + public function setCellHeaderFormat($cellHeaderFormat) + { + $this->cellHeaderFormat = $cellHeaderFormat; + + return $this; + } + + /** + * Gets header cell format. + * + * @return string + */ + public function getCellHeaderFormat() + { + return $this->cellHeaderFormat; + } + + /** + * Sets row cell format. + * + * @param string $cellRowFormat + * + * @return $this + */ + public function setCellRowFormat($cellRowFormat) + { + $this->cellRowFormat = $cellRowFormat; + + return $this; + } + + /** + * Gets row cell format. + * + * @return string + */ + public function getCellRowFormat() + { + return $this->cellRowFormat; + } + + /** + * Sets row cell content format. + * + * @param string $cellRowContentFormat + * + * @return $this + */ + public function setCellRowContentFormat($cellRowContentFormat) + { + $this->cellRowContentFormat = $cellRowContentFormat; + + return $this; + } + + /** + * Gets row cell content format. + * + * @return string + */ + public function getCellRowContentFormat() + { + return $this->cellRowContentFormat; + } + + /** + * Sets table border format. + * + * @param string $borderFormat + * + * @return $this + */ + public function setBorderFormat($borderFormat) + { + $this->borderFormat = $borderFormat; + + return $this; + } + + /** + * Gets table border format. + * + * @return string + */ + public function getBorderFormat() + { + return $this->borderFormat; + } + + /** + * Sets cell padding type. + * + * @param int $padType STR_PAD_* + * + * @return $this + */ + public function setPadType($padType) + { + if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], true)) { + throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).'); + } + + $this->padType = $padType; + + return $this; + } + + /** + * Gets cell padding type. + * + * @return int + */ + public function getPadType() + { + return $this->padType; + } +} diff --git a/www/multitube/vendor/symfony/console/Input/ArgvInput.php b/www/multitube/vendor/symfony/console/Input/ArgvInput.php new file mode 100644 index 0000000..fb2b358 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/ArgvInput.php @@ -0,0 +1,370 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * ArgvInput represents an input coming from the CLI arguments. + * + * Usage: + * + * $input = new ArgvInput(); + * + * By default, the `$_SERVER['argv']` array is used for the input values. + * + * This can be overridden by explicitly passing the input values in the constructor: + * + * $input = new ArgvInput($_SERVER['argv']); + * + * If you pass it yourself, don't forget that the first element of the array + * is the name of the running application. + * + * When passing an argument to the constructor, be sure that it respects + * the same rules as the argv one. It's almost always better to use the + * `StringInput` when you want to provide your own input. + * + * @author Fabien Potencier + * + * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html + * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02 + */ +class ArgvInput extends Input +{ + private $tokens; + private $parsed; + + /** + * @param array|null $argv An array of parameters from the CLI (in the argv format) + * @param InputDefinition|null $definition A InputDefinition instance + */ + public function __construct(array $argv = null, InputDefinition $definition = null) + { + $argv = null !== $argv ? $argv : (isset($_SERVER['argv']) ? $_SERVER['argv'] : []); + + // strip the application name + array_shift($argv); + + $this->tokens = $argv; + + parent::__construct($definition); + } + + protected function setTokens(array $tokens) + { + $this->tokens = $tokens; + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + $parseOptions = true; + $this->parsed = $this->tokens; + while (null !== $token = array_shift($this->parsed)) { + if ($parseOptions && '' == $token) { + $this->parseArgument($token); + } elseif ($parseOptions && '--' == $token) { + $parseOptions = false; + } elseif ($parseOptions && 0 === strpos($token, '--')) { + $this->parseLongOption($token); + } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) { + $this->parseShortOption($token); + } else { + $this->parseArgument($token); + } + } + } + + /** + * Parses a short option. + * + * @param string $token The current token + */ + private function parseShortOption($token) + { + $name = substr($token, 1); + + if (\strlen($name) > 1) { + if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) { + // an option with a value (with no space) + $this->addShortOption($name[0], substr($name, 1)); + } else { + $this->parseShortOptionSet($name); + } + } else { + $this->addShortOption($name, null); + } + } + + /** + * Parses a short option set. + * + * @param string $name The current token + * + * @throws RuntimeException When option given doesn't exist + */ + private function parseShortOptionSet($name) + { + $len = \strlen($name); + for ($i = 0; $i < $len; ++$i) { + if (!$this->definition->hasShortcut($name[$i])) { + $encoding = mb_detect_encoding($name, null, true); + throw new RuntimeException(sprintf('The "-%s" option does not exist.', false === $encoding ? $name[$i] : mb_substr($name, $i, 1, $encoding))); + } + + $option = $this->definition->getOptionForShortcut($name[$i]); + if ($option->acceptValue()) { + $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1)); + + break; + } else { + $this->addLongOption($option->getName(), null); + } + } + } + + /** + * Parses a long option. + * + * @param string $token The current token + */ + private function parseLongOption($token) + { + $name = substr($token, 2); + + if (false !== $pos = strpos($name, '=')) { + if (0 === \strlen($value = substr($name, $pos + 1))) { + // if no value after "=" then substr() returns "" since php7 only, false before + // see https://php.net/migration70.incompatible.php#119151 + if (\PHP_VERSION_ID < 70000 && false === $value) { + $value = ''; + } + array_unshift($this->parsed, $value); + } + $this->addLongOption(substr($name, 0, $pos), $value); + } else { + $this->addLongOption($name, null); + } + } + + /** + * Parses an argument. + * + * @param string $token The current token + * + * @throws RuntimeException When too many arguments are given + */ + private function parseArgument($token) + { + $c = \count($this->arguments); + + // if input is expecting another argument, add it + if ($this->definition->hasArgument($c)) { + $arg = $this->definition->getArgument($c); + $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token; + + // if last argument isArray(), append token to last argument + } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) { + $arg = $this->definition->getArgument($c - 1); + $this->arguments[$arg->getName()][] = $token; + + // unexpected argument + } else { + $all = $this->definition->getArguments(); + if (\count($all)) { + throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all)))); + } + + throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token)); + } + } + + /** + * Adds a short option value. + * + * @param string $shortcut The short option key + * @param mixed $value The value for the option + * + * @throws RuntimeException When option given doesn't exist + */ + private function addShortOption($shortcut, $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @param string $name The long option key + * @param mixed $value The value for the option + * + * @throws RuntimeException When option given doesn't exist + */ + private function addLongOption($name, $value) + { + if (!$this->definition->hasOption($name)) { + throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name)); + } + + $option = $this->definition->getOption($name); + + if (null !== $value && !$option->acceptValue()) { + throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name)); + } + + if (\in_array($value, ['', null], true) && $option->acceptValue() && \count($this->parsed)) { + // if option accepts an optional or mandatory argument + // let's see if there is one provided + $next = array_shift($this->parsed); + if ((isset($next[0]) && '-' !== $next[0]) || \in_array($next, ['', null], true)) { + $value = $next; + } else { + array_unshift($this->parsed, $next); + } + } + + if (null === $value) { + if ($option->isValueRequired()) { + throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isArray() && !$option->isValueOptional()) { + $value = true; + } + } + + if ($option->isArray()) { + $this->options[$name][] = $value; + } else { + $this->options[$name] = $value; + } + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument() + { + $isOption = false; + foreach ($this->tokens as $i => $token) { + if ($token && '-' === $token[0]) { + if (false !== strpos($token, '=') || !isset($this->tokens[$i + 1])) { + continue; + } + + // If it's a long option, consider that everything after "--" is the option name. + // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator) + $name = '-' === $token[1] ? substr($token, 2) : substr($token, -1); + if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) { + // noop + } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) { + $isOption = true; + } + + continue; + } + + if ($isOption) { + $isOption = false; + continue; + } + + return $token; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption($values, $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->tokens as $token) { + if ($onlyParams && '--' === $token) { + return false; + } + foreach ($values as $value) { + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ($token === $value || '' !== $leading && 0 === strpos($token, $leading)) { + return true; + } + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption($values, $default = false, $onlyParams = false) + { + $values = (array) $values; + $tokens = $this->tokens; + + while (0 < \count($tokens)) { + $token = array_shift($tokens); + if ($onlyParams && '--' === $token) { + return $default; + } + + foreach ($values as $value) { + if ($token === $value) { + return array_shift($tokens); + } + // Options with values: + // For long options, test for '--option=' at beginning + // For short options, test for '-o' at beginning + $leading = 0 === strpos($value, '--') ? $value.'=' : $value; + if ('' !== $leading && 0 === strpos($token, $leading)) { + return substr($token, \strlen($leading)); + } + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + * + * @return string + */ + public function __toString() + { + $tokens = array_map(function ($token) { + if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) { + return $match[1].$this->escapeToken($match[2]); + } + + if ($token && '-' !== $token[0]) { + return $this->escapeToken($token); + } + + return $token; + }, $this->tokens); + + return implode(' ', $tokens); + } +} diff --git a/www/multitube/vendor/symfony/console/Input/ArrayInput.php b/www/multitube/vendor/symfony/console/Input/ArrayInput.php new file mode 100644 index 0000000..b2ebc7c --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/ArrayInput.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\InvalidOptionException; + +/** + * ArrayInput represents an input provided as an array. + * + * Usage: + * + * $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']); + * + * @author Fabien Potencier + */ +class ArrayInput extends Input +{ + private $parameters; + + public function __construct(array $parameters, InputDefinition $definition = null) + { + $this->parameters = $parameters; + + parent::__construct($definition); + } + + /** + * {@inheritdoc} + */ + public function getFirstArgument() + { + foreach ($this->parameters as $param => $value) { + if ($param && \is_string($param) && '-' === $param[0]) { + continue; + } + + return $value; + } + + return null; + } + + /** + * {@inheritdoc} + */ + public function hasParameterOption($values, $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if (!\is_int($k)) { + $v = $k; + } + + if ($onlyParams && '--' === $v) { + return false; + } + + if (\in_array($v, $values)) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getParameterOption($values, $default = false, $onlyParams = false) + { + $values = (array) $values; + + foreach ($this->parameters as $k => $v) { + if ($onlyParams && ('--' === $k || (\is_int($k) && '--' === $v))) { + return $default; + } + + if (\is_int($k)) { + if (\in_array($v, $values)) { + return true; + } + } elseif (\in_array($k, $values)) { + return $v; + } + } + + return $default; + } + + /** + * Returns a stringified representation of the args passed to the command. + * + * @return string + */ + public function __toString() + { + $params = []; + foreach ($this->parameters as $param => $val) { + if ($param && \is_string($param) && '-' === $param[0]) { + if (\is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + } + } else { + $params[] = \is_array($val) ? implode(' ', array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val); + } + } + + return implode(' ', $params); + } + + /** + * {@inheritdoc} + */ + protected function parse() + { + foreach ($this->parameters as $key => $value) { + if ('--' === $key) { + return; + } + if (0 === strpos($key, '--')) { + $this->addLongOption(substr($key, 2), $value); + } elseif (0 === strpos($key, '-')) { + $this->addShortOption(substr($key, 1), $value); + } else { + $this->addArgument($key, $value); + } + } + } + + /** + * Adds a short option value. + * + * @param string $shortcut The short option key + * @param mixed $value The value for the option + * + * @throws InvalidOptionException When option given doesn't exist + */ + private function addShortOption($shortcut, $value) + { + if (!$this->definition->hasShortcut($shortcut)) { + throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value); + } + + /** + * Adds a long option value. + * + * @param string $name The long option key + * @param mixed $value The value for the option + * + * @throws InvalidOptionException When option given doesn't exist + * @throws InvalidOptionException When a required value is missing + */ + private function addLongOption($name, $value) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name)); + } + + $option = $this->definition->getOption($name); + + if (null === $value) { + if ($option->isValueRequired()) { + throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name)); + } + + if (!$option->isValueOptional()) { + $value = true; + } + } + + $this->options[$name] = $value; + } + + /** + * Adds an argument value. + * + * @param string $name The argument name + * @param mixed $value The value for the argument + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + private function addArgument($name, $value) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } +} diff --git a/www/multitube/vendor/symfony/console/Input/Input.php b/www/multitube/vendor/symfony/console/Input/Input.php new file mode 100644 index 0000000..c122031 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/Input.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * Input is the base class for all concrete Input classes. + * + * Three concrete classes are provided by default: + * + * * `ArgvInput`: The input comes from the CLI arguments (argv) + * * `StringInput`: The input is provided as a string + * * `ArrayInput`: The input is provided as an array + * + * @author Fabien Potencier + */ +abstract class Input implements InputInterface, StreamableInputInterface +{ + protected $definition; + protected $stream; + protected $options = []; + protected $arguments = []; + protected $interactive = true; + + public function __construct(InputDefinition $definition = null) + { + if (null === $definition) { + $this->definition = new InputDefinition(); + } else { + $this->bind($definition); + $this->validate(); + } + } + + /** + * {@inheritdoc} + */ + public function bind(InputDefinition $definition) + { + $this->arguments = []; + $this->options = []; + $this->definition = $definition; + + $this->parse(); + } + + /** + * Processes command line arguments. + */ + abstract protected function parse(); + + /** + * {@inheritdoc} + */ + public function validate() + { + $definition = $this->definition; + $givenArguments = $this->arguments; + + $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) { + return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired(); + }); + + if (\count($missingArguments) > 0) { + throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments))); + } + } + + /** + * {@inheritdoc} + */ + public function isInteractive() + { + return $this->interactive; + } + + /** + * {@inheritdoc} + */ + public function setInteractive($interactive) + { + $this->interactive = (bool) $interactive; + } + + /** + * {@inheritdoc} + */ + public function getArguments() + { + return array_merge($this->definition->getArgumentDefaults(), $this->arguments); + } + + /** + * {@inheritdoc} + */ + public function getArgument($name) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function setArgument($name, $value) + { + if (!$this->definition->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $this->arguments[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function hasArgument($name) + { + return $this->definition->hasArgument($name); + } + + /** + * {@inheritdoc} + */ + public function getOptions() + { + return array_merge($this->definition->getOptionDefaults(), $this->options); + } + + /** + * {@inheritdoc} + */ + public function getOption($name) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault(); + } + + /** + * {@inheritdoc} + */ + public function setOption($name, $value) + { + if (!$this->definition->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name)); + } + + $this->options[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function hasOption($name) + { + return $this->definition->hasOption($name); + } + + /** + * Escapes a token through escapeshellarg if it contains unsafe chars. + * + * @param string $token + * + * @return string + */ + public function escapeToken($token) + { + return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token); + } + + /** + * {@inheritdoc} + */ + public function setStream($stream) + { + $this->stream = $stream; + } + + /** + * {@inheritdoc} + */ + public function getStream() + { + return $this->stream; + } +} diff --git a/www/multitube/vendor/symfony/console/Input/InputArgument.php b/www/multitube/vendor/symfony/console/Input/InputArgument.php new file mode 100644 index 0000000..4c2b6a6 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/InputArgument.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line argument. + * + * @author Fabien Potencier + */ +class InputArgument +{ + const REQUIRED = 1; + const OPTIONAL = 2; + const IS_ARRAY = 4; + + private $name; + private $mode; + private $default; + private $description; + + /** + * @param string $name The argument name + * @param int|null $mode The argument mode: self::REQUIRED or self::OPTIONAL + * @param string $description A description text + * @param string|string[]|null $default The default value (for self::OPTIONAL mode only) + * + * @throws InvalidArgumentException When argument mode is not valid + */ + public function __construct($name, $mode = null, $description = '', $default = null) + { + if (null === $mode) { + $mode = self::OPTIONAL; + } elseif (!\is_int($mode) || $mode > 7 || $mode < 1) { + throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->mode = $mode; + $this->description = $description; + + $this->setDefault($default); + } + + /** + * Returns the argument name. + * + * @return string The argument name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns true if the argument is required. + * + * @return bool true if parameter mode is self::REQUIRED, false otherwise + */ + public function isRequired() + { + return self::REQUIRED === (self::REQUIRED & $this->mode); + } + + /** + * Returns true if the argument can take multiple values. + * + * @return bool true if mode is self::IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::IS_ARRAY === (self::IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @param string|string[]|null $default The default value + * + * @throws LogicException When incorrect default value is given + */ + public function setDefault($default = null) + { + if (self::REQUIRED === $this->mode && null !== $default) { + throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\is_array($default)) { + throw new LogicException('A default value for an array argument must be an array.'); + } + } + + $this->default = $default; + } + + /** + * Returns the default value. + * + * @return string|string[]|null The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } +} diff --git a/www/multitube/vendor/symfony/console/Input/InputAwareInterface.php b/www/multitube/vendor/symfony/console/Input/InputAwareInterface.php new file mode 100644 index 0000000..5a288de --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/InputAwareInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +/** + * InputAwareInterface should be implemented by classes that depends on the + * Console Input. + * + * @author Wouter J + */ +interface InputAwareInterface +{ + /** + * Sets the Console Input. + */ + public function setInput(InputInterface $input); +} diff --git a/www/multitube/vendor/symfony/console/Input/InputDefinition.php b/www/multitube/vendor/symfony/console/Input/InputDefinition.php new file mode 100644 index 0000000..d953f9b --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/InputDefinition.php @@ -0,0 +1,404 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * A InputDefinition represents a set of valid command line arguments and options. + * + * Usage: + * + * $definition = new InputDefinition([ + * new InputArgument('name', InputArgument::REQUIRED), + * new InputOption('foo', 'f', InputOption::VALUE_REQUIRED), + * ]); + * + * @author Fabien Potencier + */ +class InputDefinition +{ + private $arguments; + private $requiredCount; + private $hasAnArrayArgument = false; + private $hasOptional; + private $options; + private $shortcuts; + + /** + * @param array $definition An array of InputArgument and InputOption instance + */ + public function __construct(array $definition = []) + { + $this->setDefinition($definition); + } + + /** + * Sets the definition of the input. + */ + public function setDefinition(array $definition) + { + $arguments = []; + $options = []; + foreach ($definition as $item) { + if ($item instanceof InputOption) { + $options[] = $item; + } else { + $arguments[] = $item; + } + } + + $this->setArguments($arguments); + $this->setOptions($options); + } + + /** + * Sets the InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function setArguments($arguments = []) + { + $this->arguments = []; + $this->requiredCount = 0; + $this->hasOptional = false; + $this->hasAnArrayArgument = false; + $this->addArguments($arguments); + } + + /** + * Adds an array of InputArgument objects. + * + * @param InputArgument[] $arguments An array of InputArgument objects + */ + public function addArguments($arguments = []) + { + if (null !== $arguments) { + foreach ($arguments as $argument) { + $this->addArgument($argument); + } + } + } + + /** + * @throws LogicException When incorrect argument is given + */ + public function addArgument(InputArgument $argument) + { + if (isset($this->arguments[$argument->getName()])) { + throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName())); + } + + if ($this->hasAnArrayArgument) { + throw new LogicException('Cannot add an argument after an array argument.'); + } + + if ($argument->isRequired() && $this->hasOptional) { + throw new LogicException('Cannot add a required argument after an optional one.'); + } + + if ($argument->isArray()) { + $this->hasAnArrayArgument = true; + } + + if ($argument->isRequired()) { + ++$this->requiredCount; + } else { + $this->hasOptional = true; + } + + $this->arguments[$argument->getName()] = $argument; + } + + /** + * Returns an InputArgument by name or by position. + * + * @param string|int $name The InputArgument name or position + * + * @return InputArgument An InputArgument object + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument($name) + { + if (!$this->hasArgument($name)) { + throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name)); + } + + $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; + + return $arguments[$name]; + } + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|int $name The InputArgument name or position + * + * @return bool true if the InputArgument object exists, false otherwise + */ + public function hasArgument($name) + { + $arguments = \is_int($name) ? array_values($this->arguments) : $this->arguments; + + return isset($arguments[$name]); + } + + /** + * Gets the array of InputArgument objects. + * + * @return InputArgument[] An array of InputArgument objects + */ + public function getArguments() + { + return $this->arguments; + } + + /** + * Returns the number of InputArguments. + * + * @return int The number of InputArguments + */ + public function getArgumentCount() + { + return $this->hasAnArrayArgument ? \PHP_INT_MAX : \count($this->arguments); + } + + /** + * Returns the number of required InputArguments. + * + * @return int The number of required InputArguments + */ + public function getArgumentRequiredCount() + { + return $this->requiredCount; + } + + /** + * Gets the default values. + * + * @return array An array of default values + */ + public function getArgumentDefaults() + { + $values = []; + foreach ($this->arguments as $argument) { + $values[$argument->getName()] = $argument->getDefault(); + } + + return $values; + } + + /** + * Sets the InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function setOptions($options = []) + { + $this->options = []; + $this->shortcuts = []; + $this->addOptions($options); + } + + /** + * Adds an array of InputOption objects. + * + * @param InputOption[] $options An array of InputOption objects + */ + public function addOptions($options = []) + { + foreach ($options as $option) { + $this->addOption($option); + } + } + + /** + * @throws LogicException When option given already exist + */ + public function addOption(InputOption $option) + { + if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) { + throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName())); + } + + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) { + throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut)); + } + } + } + + $this->options[$option->getName()] = $option; + if ($option->getShortcut()) { + foreach (explode('|', $option->getShortcut()) as $shortcut) { + $this->shortcuts[$shortcut] = $option->getName(); + } + } + } + + /** + * Returns an InputOption by name. + * + * @param string $name The InputOption name + * + * @return InputOption A InputOption object + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption($name) + { + if (!$this->hasOption($name)) { + throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name)); + } + + return $this->options[$name]; + } + + /** + * Returns true if an InputOption object exists by name. + * + * This method can't be used to check if the user included the option when + * executing the command (use getOption() instead). + * + * @param string $name The InputOption name + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasOption($name) + { + return isset($this->options[$name]); + } + + /** + * Gets the array of InputOption objects. + * + * @return InputOption[] An array of InputOption objects + */ + public function getOptions() + { + return $this->options; + } + + /** + * Returns true if an InputOption object exists by shortcut. + * + * @param string $name The InputOption shortcut + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasShortcut($name) + { + return isset($this->shortcuts[$name]); + } + + /** + * Gets an InputOption by shortcut. + * + * @param string $shortcut The Shortcut name + * + * @return InputOption An InputOption object + */ + public function getOptionForShortcut($shortcut) + { + return $this->getOption($this->shortcutToName($shortcut)); + } + + /** + * Gets an array of default values. + * + * @return array An array of all default values + */ + public function getOptionDefaults() + { + $values = []; + foreach ($this->options as $option) { + $values[$option->getName()] = $option->getDefault(); + } + + return $values; + } + + /** + * Returns the InputOption name given a shortcut. + * + * @param string $shortcut The shortcut + * + * @return string The InputOption name + * + * @throws InvalidArgumentException When option given does not exist + * + * @internal + */ + public function shortcutToName($shortcut) + { + if (!isset($this->shortcuts[$shortcut])) { + throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut)); + } + + return $this->shortcuts[$shortcut]; + } + + /** + * Gets the synopsis. + * + * @param bool $short Whether to return the short version (with options folded) or not + * + * @return string The synopsis + */ + public function getSynopsis($short = false) + { + $elements = []; + + if ($short && $this->getOptions()) { + $elements[] = '[options]'; + } elseif (!$short) { + foreach ($this->getOptions() as $option) { + $value = ''; + if ($option->acceptValue()) { + $value = sprintf( + ' %s%s%s', + $option->isValueOptional() ? '[' : '', + strtoupper($option->getName()), + $option->isValueOptional() ? ']' : '' + ); + } + + $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : ''; + $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value); + } + } + + if (\count($elements) && $this->getArguments()) { + $elements[] = '[--]'; + } + + foreach ($this->getArguments() as $argument) { + $element = '<'.$argument->getName().'>'; + if (!$argument->isRequired()) { + $element = '['.$element.']'; + } elseif ($argument->isArray()) { + $element .= ' ('.$element.')'; + } + + if ($argument->isArray()) { + $element .= '...'; + } + + $elements[] = $element; + } + + return implode(' ', $elements); + } +} diff --git a/www/multitube/vendor/symfony/console/Input/InputInterface.php b/www/multitube/vendor/symfony/console/Input/InputInterface.php new file mode 100644 index 0000000..b9bcf3b --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/InputInterface.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; + +/** + * InputInterface is the interface implemented by all input classes. + * + * @author Fabien Potencier + */ +interface InputInterface +{ + /** + * Returns the first argument from the raw parameters (not parsed). + * + * @return string|null The value of the first argument or null otherwise + */ + public function getFirstArgument(); + + /** + * Returns true if the raw parameters (not parsed) contain a value. + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The values to look for in the raw parameters (can be an array) + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return bool true if the value is contained in the raw parameters + */ + public function hasParameterOption($values, $onlyParams = false); + + /** + * Returns the value of a raw option (not parsed). + * + * This method is to be used to introspect the input parameters + * before they have been validated. It must be used carefully. + * Does not necessarily return the correct result for short options + * when multiple flags are combined in the same option. + * + * @param string|array $values The value(s) to look for in the raw parameters (can be an array) + * @param mixed $default The default value to return if no result is found + * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal + * + * @return mixed The option value + */ + public function getParameterOption($values, $default = false, $onlyParams = false); + + /** + * Binds the current Input instance with the given arguments and options. + * + * @throws RuntimeException + */ + public function bind(InputDefinition $definition); + + /** + * Validates the input. + * + * @throws RuntimeException When not enough arguments are given + */ + public function validate(); + + /** + * Returns all the given arguments merged with the default values. + * + * @return array + */ + public function getArguments(); + + /** + * Returns the argument value for a given argument name. + * + * @param string $name The argument name + * + * @return string|string[]|null The argument value + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function getArgument($name); + + /** + * Sets an argument value by name. + * + * @param string $name The argument name + * @param string|string[]|null $value The argument value + * + * @throws InvalidArgumentException When argument given doesn't exist + */ + public function setArgument($name, $value); + + /** + * Returns true if an InputArgument object exists by name or position. + * + * @param string|int $name The InputArgument name or position + * + * @return bool true if the InputArgument object exists, false otherwise + */ + public function hasArgument($name); + + /** + * Returns all the given options merged with the default values. + * + * @return array + */ + public function getOptions(); + + /** + * Returns the option value for a given option name. + * + * @param string $name The option name + * + * @return string|string[]|bool|null The option value + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function getOption($name); + + /** + * Sets an option value by name. + * + * @param string $name The option name + * @param string|string[]|bool|null $value The option value + * + * @throws InvalidArgumentException When option given doesn't exist + */ + public function setOption($name, $value); + + /** + * Returns true if an InputOption object exists by name. + * + * @param string $name The InputOption name + * + * @return bool true if the InputOption object exists, false otherwise + */ + public function hasOption($name); + + /** + * Is this input means interactive? + * + * @return bool + */ + public function isInteractive(); + + /** + * Sets the input interactivity. + * + * @param bool $interactive If the input should be interactive + */ + public function setInteractive($interactive); +} diff --git a/www/multitube/vendor/symfony/console/Input/InputOption.php b/www/multitube/vendor/symfony/console/Input/InputOption.php new file mode 100644 index 0000000..b0bd28f --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/InputOption.php @@ -0,0 +1,208 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a command line option. + * + * @author Fabien Potencier + */ +class InputOption +{ + const VALUE_NONE = 1; + const VALUE_REQUIRED = 2; + const VALUE_OPTIONAL = 4; + const VALUE_IS_ARRAY = 8; + + private $name; + private $shortcut; + private $mode; + private $default; + private $description; + + /** + * @param string $name The option name + * @param string|array|null $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts + * @param int|null $mode The option mode: One of the VALUE_* constants + * @param string $description A description text + * @param string|string[]|int|bool|null $default The default value (must be null for self::VALUE_NONE) + * + * @throws InvalidArgumentException If option mode is invalid or incompatible + */ + public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null) + { + if (0 === strpos($name, '--')) { + $name = substr($name, 2); + } + + if (empty($name)) { + throw new InvalidArgumentException('An option name cannot be empty.'); + } + + if (empty($shortcut)) { + $shortcut = null; + } + + if (null !== $shortcut) { + if (\is_array($shortcut)) { + $shortcut = implode('|', $shortcut); + } + $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-')); + $shortcuts = array_filter($shortcuts); + $shortcut = implode('|', $shortcuts); + + if (empty($shortcut)) { + throw new InvalidArgumentException('An option shortcut cannot be empty.'); + } + } + + if (null === $mode) { + $mode = self::VALUE_NONE; + } elseif (!\is_int($mode) || $mode > 15 || $mode < 1) { + throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode)); + } + + $this->name = $name; + $this->shortcut = $shortcut; + $this->mode = $mode; + $this->description = $description; + + if ($this->isArray() && !$this->acceptValue()) { + throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.'); + } + + $this->setDefault($default); + } + + /** + * Returns the option shortcut. + * + * @return string|null The shortcut + */ + public function getShortcut() + { + return $this->shortcut; + } + + /** + * Returns the option name. + * + * @return string The name + */ + public function getName() + { + return $this->name; + } + + /** + * Returns true if the option accepts a value. + * + * @return bool true if value mode is not self::VALUE_NONE, false otherwise + */ + public function acceptValue() + { + return $this->isValueRequired() || $this->isValueOptional(); + } + + /** + * Returns true if the option requires a value. + * + * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise + */ + public function isValueRequired() + { + return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode); + } + + /** + * Returns true if the option takes an optional value. + * + * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise + */ + public function isValueOptional() + { + return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode); + } + + /** + * Returns true if the option can take multiple values. + * + * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise + */ + public function isArray() + { + return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode); + } + + /** + * Sets the default value. + * + * @param string|string[]|int|bool|null $default The default value + * + * @throws LogicException When incorrect default value is given + */ + public function setDefault($default = null) + { + if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) { + throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.'); + } + + if ($this->isArray()) { + if (null === $default) { + $default = []; + } elseif (!\is_array($default)) { + throw new LogicException('A default value for an array option must be an array.'); + } + } + + $this->default = $this->acceptValue() ? $default : false; + } + + /** + * Returns the default value. + * + * @return string|string[]|int|bool|null The default value + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns the description text. + * + * @return string The description text + */ + public function getDescription() + { + return $this->description; + } + + /** + * Checks whether the given option equals this one. + * + * @return bool + */ + public function equals(self $option) + { + return $option->getName() === $this->getName() + && $option->getShortcut() === $this->getShortcut() + && $option->getDefault() === $this->getDefault() + && $option->isArray() === $this->isArray() + && $option->isValueRequired() === $this->isValueRequired() + && $option->isValueOptional() === $this->isValueOptional() + ; + } +} diff --git a/www/multitube/vendor/symfony/console/Input/StreamableInputInterface.php b/www/multitube/vendor/symfony/console/Input/StreamableInputInterface.php new file mode 100644 index 0000000..d7e462f --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/StreamableInputInterface.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +/** + * StreamableInputInterface is the interface implemented by all input classes + * that have an input stream. + * + * @author Robin Chalas + */ +interface StreamableInputInterface extends InputInterface +{ + /** + * Sets the input stream to read from when interacting with the user. + * + * This is mainly useful for testing purpose. + * + * @param resource $stream The input stream + */ + public function setStream($stream); + + /** + * Returns the input stream. + * + * @return resource|null + */ + public function getStream(); +} diff --git a/www/multitube/vendor/symfony/console/Input/StringInput.php b/www/multitube/vendor/symfony/console/Input/StringInput.php new file mode 100644 index 0000000..5032b34 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Input/StringInput.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Input; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * StringInput represents an input provided as a string. + * + * Usage: + * + * $input = new StringInput('foo --bar="foobar"'); + * + * @author Fabien Potencier + */ +class StringInput extends ArgvInput +{ + const REGEX_STRING = '([^\s]+?)(?:\s|(?setTokens($this->tokenize($input)); + } + + /** + * Tokenizes a string. + * + * @param string $input The input to tokenize + * + * @return array An array of tokens + * + * @throws InvalidArgumentException When unable to parse input (should never happen) + */ + private function tokenize($input) + { + $tokens = []; + $length = \strlen($input); + $cursor = 0; + while ($cursor < $length) { + if (preg_match('/\s+/A', $input, $match, null, $cursor)) { + } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) { + $tokens[] = $match[1].$match[2].stripcslashes(str_replace(['"\'', '\'"', '\'\'', '""'], '', substr($match[3], 1, \strlen($match[3]) - 2))); + } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) { + $tokens[] = stripcslashes(substr($match[0], 1, \strlen($match[0]) - 2)); + } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) { + $tokens[] = stripcslashes($match[1]); + } else { + // should never happen + throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ...".', substr($input, $cursor, 10))); + } + + $cursor += \strlen($match[0]); + } + + return $tokens; + } +} diff --git a/www/multitube/vendor/symfony/console/LICENSE b/www/multitube/vendor/symfony/console/LICENSE new file mode 100644 index 0000000..9e936ec --- /dev/null +++ b/www/multitube/vendor/symfony/console/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/symfony/console/Logger/ConsoleLogger.php b/www/multitube/vendor/symfony/console/Logger/ConsoleLogger.php new file mode 100644 index 0000000..6b1745e --- /dev/null +++ b/www/multitube/vendor/symfony/console/Logger/ConsoleLogger.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Logger; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * PSR-3 compliant console logger. + * + * @author Kévin Dunglas + * + * @see https://www.php-fig.org/psr/psr-3/ + */ +class ConsoleLogger extends AbstractLogger +{ + const INFO = 'info'; + const ERROR = 'error'; + + private $output; + private $verbosityLevelMap = [ + LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, + LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, + LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, + LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, + LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, + LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, + LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG, + ]; + private $formatLevelMap = [ + LogLevel::EMERGENCY => self::ERROR, + LogLevel::ALERT => self::ERROR, + LogLevel::CRITICAL => self::ERROR, + LogLevel::ERROR => self::ERROR, + LogLevel::WARNING => self::INFO, + LogLevel::NOTICE => self::INFO, + LogLevel::INFO => self::INFO, + LogLevel::DEBUG => self::INFO, + ]; + private $errored = false; + + public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = []) + { + $this->output = $output; + $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap; + $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap; + } + + /** + * {@inheritdoc} + */ + public function log($level, $message, array $context = []) + { + if (!isset($this->verbosityLevelMap[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + $output = $this->output; + + // Write to the error output if necessary and available + if (self::ERROR === $this->formatLevelMap[$level]) { + if ($this->output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + $this->errored = true; + } + + // the if condition check isn't necessary -- it's the same one that $output will do internally anyway. + // We only do it for efficiency here as the message formatting is relatively expensive. + if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) { + $output->writeln(sprintf('<%1$s>[%2$s] %3$s', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]); + } + } + + /** + * Returns true when any messages have been logged at error levels. + * + * @return bool + */ + public function hasErrored() + { + return $this->errored; + } + + /** + * Interpolates context values into the message placeholders. + * + * @author PHP Framework Interoperability Group + * + * @param string $message + * + * @return string + */ + private function interpolate($message, array $context) + { + if (false === strpos($message, '{')) { + return $message; + } + + $replacements = []; + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + return strtr($message, $replacements); + } +} diff --git a/www/multitube/vendor/symfony/console/Output/BufferedOutput.php b/www/multitube/vendor/symfony/console/Output/BufferedOutput.php new file mode 100644 index 0000000..fefaac2 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/BufferedOutput.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +/** + * @author Jean-François Simon + */ +class BufferedOutput extends Output +{ + private $buffer = ''; + + /** + * Empties buffer and returns its content. + * + * @return string + */ + public function fetch() + { + $content = $this->buffer; + $this->buffer = ''; + + return $content; + } + + /** + * {@inheritdoc} + */ + protected function doWrite($message, $newline) + { + $this->buffer .= $message; + + if ($newline) { + $this->buffer .= \PHP_EOL; + } + } +} diff --git a/www/multitube/vendor/symfony/console/Output/ConsoleOutput.php b/www/multitube/vendor/symfony/console/Output/ConsoleOutput.php new file mode 100644 index 0000000..21a108f --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/ConsoleOutput.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR. + * + * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR. + * + * $output = new ConsoleOutput(); + * + * This is equivalent to: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * $stdErr = new StreamOutput(fopen('php://stderr', 'w')); + * + * @author Fabien Potencier + */ +class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface +{ + private $stderr; + + /** + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) + { + parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter); + + $actualDecorated = $this->isDecorated(); + $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter()); + + if (null === $decorated) { + $this->setDecorated($actualDecorated && $this->stderr->isDecorated()); + } + } + + /** + * {@inheritdoc} + */ + public function setDecorated($decorated) + { + parent::setDecorated($decorated); + $this->stderr->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + parent::setFormatter($formatter); + $this->stderr->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity($level) + { + parent::setVerbosity($level); + $this->stderr->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getErrorOutput() + { + return $this->stderr; + } + + /** + * {@inheritdoc} + */ + public function setErrorOutput(OutputInterface $error) + { + $this->stderr = $error; + } + + /** + * Returns true if current environment supports writing console output to + * STDOUT. + * + * @return bool + */ + protected function hasStdoutSupport() + { + return false === $this->isRunningOS400(); + } + + /** + * Returns true if current environment supports writing console output to + * STDERR. + * + * @return bool + */ + protected function hasStderrSupport() + { + return false === $this->isRunningOS400(); + } + + /** + * Checks if current executing environment is IBM iSeries (OS400), which + * doesn't properly convert character-encodings between ASCII to EBCDIC. + * + * @return bool + */ + private function isRunningOS400() + { + $checks = [ + \function_exists('php_uname') ? php_uname('s') : '', + getenv('OSTYPE'), + \PHP_OS, + ]; + + return false !== stripos(implode(';', $checks), 'OS400'); + } + + /** + * @return resource + */ + private function openOutputStream() + { + if (!$this->hasStdoutSupport()) { + return fopen('php://output', 'w'); + } + + return @fopen('php://stdout', 'w') ?: fopen('php://output', 'w'); + } + + /** + * @return resource + */ + private function openErrorStream() + { + return fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w'); + } +} diff --git a/www/multitube/vendor/symfony/console/Output/ConsoleOutputInterface.php b/www/multitube/vendor/symfony/console/Output/ConsoleOutputInterface.php new file mode 100644 index 0000000..b44ea7e --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/ConsoleOutputInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +/** + * ConsoleOutputInterface is the interface implemented by ConsoleOutput class. + * This adds information about stderr output stream. + * + * @author Dariusz Górecki + */ +interface ConsoleOutputInterface extends OutputInterface +{ + /** + * Gets the OutputInterface for errors. + * + * @return OutputInterface + */ + public function getErrorOutput(); + + public function setErrorOutput(OutputInterface $error); +} diff --git a/www/multitube/vendor/symfony/console/Output/NullOutput.php b/www/multitube/vendor/symfony/console/Output/NullOutput.php new file mode 100644 index 0000000..218f285 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/NullOutput.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * NullOutput suppresses all output. + * + * $output = new NullOutput(); + * + * @author Fabien Potencier + * @author Tobias Schultze + */ +class NullOutput implements OutputInterface +{ + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + // to comply with the interface we must return a OutputFormatterInterface + return new OutputFormatter(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated($decorated) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function setVerbosity($level) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return self::VERBOSITY_QUIET; + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, $options = self::OUTPUT_NORMAL) + { + // do nothing + } + + /** + * {@inheritdoc} + */ + public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL) + { + // do nothing + } +} diff --git a/www/multitube/vendor/symfony/console/Output/Output.php b/www/multitube/vendor/symfony/console/Output/Output.php new file mode 100644 index 0000000..c3856cc --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/Output.php @@ -0,0 +1,175 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * Base class for output classes. + * + * There are five levels of verbosity: + * + * * normal: no option passed (normal output) + * * verbose: -v (more output) + * * very verbose: -vv (highly extended output) + * * debug: -vvv (all debug output) + * * quiet: -q (no output) + * + * @author Fabien Potencier + */ +abstract class Output implements OutputInterface +{ + private $verbosity; + private $formatter; + + /** + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool $decorated Whether to decorate messages + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + */ + public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null) + { + $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity; + $this->formatter = $formatter ?: new OutputFormatter(); + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->formatter = $formatter; + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->formatter; + } + + /** + * {@inheritdoc} + */ + public function setDecorated($decorated) + { + $this->formatter->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->formatter->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity($level) + { + $this->verbosity = (int) $level; + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return self::VERBOSITY_QUIET === $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return self::VERBOSITY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return self::VERBOSITY_DEBUG <= $this->verbosity; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, $options = self::OUTPUT_NORMAL) + { + $this->write($messages, true, $options); + } + + /** + * {@inheritdoc} + */ + public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL) + { + $messages = (array) $messages; + + $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN; + $type = $types & $options ?: self::OUTPUT_NORMAL; + + $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG; + $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL; + + if ($verbosity > $this->getVerbosity()) { + return; + } + + foreach ($messages as $message) { + switch ($type) { + case OutputInterface::OUTPUT_NORMAL: + $message = $this->formatter->format($message); + break; + case OutputInterface::OUTPUT_RAW: + break; + case OutputInterface::OUTPUT_PLAIN: + $message = strip_tags($this->formatter->format($message)); + break; + } + + $this->doWrite($message, $newline); + } + } + + /** + * Writes a message to the output. + * + * @param string $message A message to write to the output + * @param bool $newline Whether to add a newline or not + */ + abstract protected function doWrite($message, $newline); +} diff --git a/www/multitube/vendor/symfony/console/Output/OutputInterface.php b/www/multitube/vendor/symfony/console/Output/OutputInterface.php new file mode 100644 index 0000000..ad785a4 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/OutputInterface.php @@ -0,0 +1,114 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * OutputInterface is the interface implemented by all Output classes. + * + * @author Fabien Potencier + */ +interface OutputInterface +{ + const VERBOSITY_QUIET = 16; + const VERBOSITY_NORMAL = 32; + const VERBOSITY_VERBOSE = 64; + const VERBOSITY_VERY_VERBOSE = 128; + const VERBOSITY_DEBUG = 256; + + const OUTPUT_NORMAL = 1; + const OUTPUT_RAW = 2; + const OUTPUT_PLAIN = 4; + + /** + * Writes a message to the output. + * + * @param string|array $messages The message as an array of strings or a single string + * @param bool $newline Whether to add a newline + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function write($messages, $newline = false, $options = 0); + + /** + * Writes a message to the output and adds a newline at the end. + * + * @param string|array $messages The message as an array of strings or a single string + * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL + */ + public function writeln($messages, $options = 0); + + /** + * Sets the verbosity of the output. + * + * @param int $level The level of verbosity (one of the VERBOSITY constants) + */ + public function setVerbosity($level); + + /** + * Gets the current verbosity of the output. + * + * @return int The current level of verbosity (one of the VERBOSITY constants) + */ + public function getVerbosity(); + + /** + * Returns whether verbosity is quiet (-q). + * + * @return bool true if verbosity is set to VERBOSITY_QUIET, false otherwise + */ + public function isQuiet(); + + /** + * Returns whether verbosity is verbose (-v). + * + * @return bool true if verbosity is set to VERBOSITY_VERBOSE, false otherwise + */ + public function isVerbose(); + + /** + * Returns whether verbosity is very verbose (-vv). + * + * @return bool true if verbosity is set to VERBOSITY_VERY_VERBOSE, false otherwise + */ + public function isVeryVerbose(); + + /** + * Returns whether verbosity is debug (-vvv). + * + * @return bool true if verbosity is set to VERBOSITY_DEBUG, false otherwise + */ + public function isDebug(); + + /** + * Sets the decorated flag. + * + * @param bool $decorated Whether to decorate the messages + */ + public function setDecorated($decorated); + + /** + * Gets the decorated flag. + * + * @return bool true if the output will decorate messages, false otherwise + */ + public function isDecorated(); + + public function setFormatter(OutputFormatterInterface $formatter); + + /** + * Returns current output formatter instance. + * + * @return OutputFormatterInterface + */ + public function getFormatter(); +} diff --git a/www/multitube/vendor/symfony/console/Output/StreamOutput.php b/www/multitube/vendor/symfony/console/Output/StreamOutput.php new file mode 100644 index 0000000..451051d --- /dev/null +++ b/www/multitube/vendor/symfony/console/Output/StreamOutput.php @@ -0,0 +1,120 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Output; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Formatter\OutputFormatterInterface; + +/** + * StreamOutput writes the output to a given stream. + * + * Usage: + * + * $output = new StreamOutput(fopen('php://stdout', 'w')); + * + * As `StreamOutput` can use any stream, you can also use a file: + * + * $output = new StreamOutput(fopen('/path/to/output.log', 'a', false)); + * + * @author Fabien Potencier + */ +class StreamOutput extends Output +{ + private $stream; + + /** + * @param resource $stream A stream resource + * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) + * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) + * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) + * + * @throws InvalidArgumentException When first argument is not a real stream + */ + public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null) + { + if (!\is_resource($stream) || 'stream' !== get_resource_type($stream)) { + throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.'); + } + + $this->stream = $stream; + + if (null === $decorated) { + $decorated = $this->hasColorSupport(); + } + + parent::__construct($verbosity, $decorated, $formatter); + } + + /** + * Gets the stream attached to this StreamOutput instance. + * + * @return resource A stream resource + */ + public function getStream() + { + return $this->stream; + } + + /** + * {@inheritdoc} + */ + protected function doWrite($message, $newline) + { + if ($newline) { + $message .= \PHP_EOL; + } + + @fwrite($this->stream, $message); + + fflush($this->stream); + } + + /** + * Returns true if the stream supports colorization. + * + * Colorization is disabled if not supported by the stream: + * + * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo + * terminals via named pipes, so we can only check the environment. + * + * Reference: Composer\XdebugHandler\Process::supportsColor + * https://github.com/composer/xdebug-handler + * + * @return bool true if the stream supports colorization, false otherwise + */ + protected function hasColorSupport() + { + if ('Hyper' === getenv('TERM_PROGRAM')) { + return true; + } + + if (\DIRECTORY_SEPARATOR === '\\') { + return (\function_exists('sapi_windows_vt100_support') + && @sapi_windows_vt100_support($this->stream)) + || false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM'); + } + + if (\function_exists('stream_isatty')) { + return @stream_isatty($this->stream); + } + + if (\function_exists('posix_isatty')) { + return @posix_isatty($this->stream); + } + + $stat = @fstat($this->stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } +} diff --git a/www/multitube/vendor/symfony/console/Question/ChoiceQuestion.php b/www/multitube/vendor/symfony/console/Question/ChoiceQuestion.php new file mode 100644 index 0000000..6253284 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Question/ChoiceQuestion.php @@ -0,0 +1,187 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; + +/** + * Represents a choice question. + * + * @author Fabien Potencier + */ +class ChoiceQuestion extends Question +{ + private $choices; + private $multiselect = false; + private $prompt = ' > '; + private $errorMessage = 'Value "%s" is invalid'; + + /** + * @param string $question The question to ask to the user + * @param array $choices The list of available choices + * @param mixed $default The default answer to return + */ + public function __construct($question, array $choices, $default = null) + { + if (!$choices) { + throw new \LogicException('Choice question must have at least 1 choice available.'); + } + + parent::__construct($question, $default); + + $this->choices = $choices; + $this->setValidator($this->getDefaultValidator()); + $this->setAutocompleterValues($choices); + } + + /** + * Returns available choices. + * + * @return array + */ + public function getChoices() + { + return $this->choices; + } + + /** + * Sets multiselect option. + * + * When multiselect is set to true, multiple choices can be answered. + * + * @param bool $multiselect + * + * @return $this + */ + public function setMultiselect($multiselect) + { + $this->multiselect = $multiselect; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + /** + * Returns whether the choices are multiselect. + * + * @return bool + */ + public function isMultiselect() + { + return $this->multiselect; + } + + /** + * Gets the prompt for choices. + * + * @return string + */ + public function getPrompt() + { + return $this->prompt; + } + + /** + * Sets the prompt for choices. + * + * @param string $prompt + * + * @return $this + */ + public function setPrompt($prompt) + { + $this->prompt = $prompt; + + return $this; + } + + /** + * Sets the error message for invalid values. + * + * The error message has a string placeholder (%s) for the invalid value. + * + * @param string $errorMessage + * + * @return $this + */ + public function setErrorMessage($errorMessage) + { + $this->errorMessage = $errorMessage; + $this->setValidator($this->getDefaultValidator()); + + return $this; + } + + /** + * Returns the default answer validator. + * + * @return callable + */ + private function getDefaultValidator() + { + $choices = $this->choices; + $errorMessage = $this->errorMessage; + $multiselect = $this->multiselect; + $isAssoc = $this->isAssoc($choices); + + return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) { + if ($multiselect) { + // Check for a separated comma values + if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) { + throw new InvalidArgumentException(sprintf($errorMessage, $selected)); + } + + $selectedChoices = array_map('trim', explode(',', $selected)); + } else { + $selectedChoices = [trim($selected)]; + } + + $multiselectChoices = []; + foreach ($selectedChoices as $value) { + $results = []; + foreach ($choices as $key => $choice) { + if ($choice === $value) { + $results[] = $key; + } + } + + if (\count($results) > 1) { + throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of "%s".', implode('" or "', $results))); + } + + $result = array_search($value, $choices); + + if (!$isAssoc) { + if (false !== $result) { + $result = $choices[$result]; + } elseif (isset($choices[$value])) { + $result = $choices[$value]; + } + } elseif (false === $result && isset($choices[$value])) { + $result = $value; + } + + if (false === $result) { + throw new InvalidArgumentException(sprintf($errorMessage, $value)); + } + + $multiselectChoices[] = (string) $result; + } + + if ($multiselect) { + return $multiselectChoices; + } + + return current($multiselectChoices); + }; + } +} diff --git a/www/multitube/vendor/symfony/console/Question/ConfirmationQuestion.php b/www/multitube/vendor/symfony/console/Question/ConfirmationQuestion.php new file mode 100644 index 0000000..d871fb8 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Question/ConfirmationQuestion.php @@ -0,0 +1,59 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +/** + * Represents a yes/no question. + * + * @author Fabien Potencier + */ +class ConfirmationQuestion extends Question +{ + private $trueAnswerRegex; + + /** + * @param string $question The question to ask to the user + * @param bool $default The default answer to return, true or false + * @param string $trueAnswerRegex A regex to match the "yes" answer + */ + public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i') + { + parent::__construct($question, (bool) $default); + + $this->trueAnswerRegex = $trueAnswerRegex; + $this->setNormalizer($this->getDefaultNormalizer()); + } + + /** + * Returns the default answer normalizer. + * + * @return callable + */ + private function getDefaultNormalizer() + { + $default = $this->getDefault(); + $regex = $this->trueAnswerRegex; + + return function ($answer) use ($default, $regex) { + if (\is_bool($answer)) { + return $answer; + } + + $answerIsTrue = (bool) preg_match($regex, $answer); + if (false === $default) { + return $answer && $answerIsTrue; + } + + return '' === $answer || $answerIsTrue; + }; + } +} diff --git a/www/multitube/vendor/symfony/console/Question/Question.php b/www/multitube/vendor/symfony/console/Question/Question.php new file mode 100644 index 0000000..7d016ec --- /dev/null +++ b/www/multitube/vendor/symfony/console/Question/Question.php @@ -0,0 +1,245 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Question; + +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\LogicException; + +/** + * Represents a Question. + * + * @author Fabien Potencier + */ +class Question +{ + private $question; + private $attempts; + private $hidden = false; + private $hiddenFallback = true; + private $autocompleterValues; + private $validator; + private $default; + private $normalizer; + + /** + * @param string $question The question to ask to the user + * @param mixed $default The default answer to return if the user enters nothing + */ + public function __construct($question, $default = null) + { + $this->question = $question; + $this->default = $default; + } + + /** + * Returns the question. + * + * @return string + */ + public function getQuestion() + { + return $this->question; + } + + /** + * Returns the default answer. + * + * @return mixed + */ + public function getDefault() + { + return $this->default; + } + + /** + * Returns whether the user response must be hidden. + * + * @return bool + */ + public function isHidden() + { + return $this->hidden; + } + + /** + * Sets whether the user response must be hidden or not. + * + * @param bool $hidden + * + * @return $this + * + * @throws LogicException In case the autocompleter is also used + */ + public function setHidden($hidden) + { + if ($this->autocompleterValues) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->hidden = (bool) $hidden; + + return $this; + } + + /** + * In case the response can not be hidden, whether to fallback on non-hidden question or not. + * + * @return bool + */ + public function isHiddenFallback() + { + return $this->hiddenFallback; + } + + /** + * Sets whether to fallback on non-hidden question if the response can not be hidden. + * + * @param bool $fallback + * + * @return $this + */ + public function setHiddenFallback($fallback) + { + $this->hiddenFallback = (bool) $fallback; + + return $this; + } + + /** + * Gets values for the autocompleter. + * + * @return iterable|null + */ + public function getAutocompleterValues() + { + return $this->autocompleterValues; + } + + /** + * Sets values for the autocompleter. + * + * @param iterable|null $values + * + * @return $this + * + * @throws InvalidArgumentException + * @throws LogicException + */ + public function setAutocompleterValues($values) + { + if (\is_array($values)) { + $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values); + } + + if (null !== $values && !\is_array($values) && !$values instanceof \Traversable) { + throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or a `Traversable` object.'); + } + + if ($this->hidden) { + throw new LogicException('A hidden question cannot use the autocompleter.'); + } + + $this->autocompleterValues = $values; + + return $this; + } + + /** + * Sets a validator for the question. + * + * @return $this + */ + public function setValidator(callable $validator = null) + { + $this->validator = $validator; + + return $this; + } + + /** + * Gets the validator for the question. + * + * @return callable|null + */ + public function getValidator() + { + return $this->validator; + } + + /** + * Sets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @param int|null $attempts + * + * @return $this + * + * @throws InvalidArgumentException in case the number of attempts is invalid + */ + public function setMaxAttempts($attempts) + { + if (null !== $attempts) { + $attempts = (int) $attempts; + if ($attempts < 1) { + throw new InvalidArgumentException('Maximum number of attempts must be a positive value.'); + } + } + + $this->attempts = $attempts; + + return $this; + } + + /** + * Gets the maximum number of attempts. + * + * Null means an unlimited number of attempts. + * + * @return int|null + */ + public function getMaxAttempts() + { + return $this->attempts; + } + + /** + * Sets a normalizer for the response. + * + * The normalizer can be a callable (a string), a closure or a class implementing __invoke. + * + * @return $this + */ + public function setNormalizer(callable $normalizer) + { + $this->normalizer = $normalizer; + + return $this; + } + + /** + * Gets the normalizer for the response. + * + * The normalizer can ba a callable (a string), a closure or a class implementing __invoke. + * + * @return callable|null + */ + public function getNormalizer() + { + return $this->normalizer; + } + + protected function isAssoc($array) + { + return (bool) \count(array_filter(array_keys($array), 'is_string')); + } +} diff --git a/www/multitube/vendor/symfony/console/README.md b/www/multitube/vendor/symfony/console/README.md new file mode 100644 index 0000000..3e2fc60 --- /dev/null +++ b/www/multitube/vendor/symfony/console/README.md @@ -0,0 +1,20 @@ +Console Component +================= + +The Console component eases the creation of beautiful and testable command line +interfaces. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/console.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) + +Credits +------- + +`Resources/bin/hiddeninput.exe` is a third party binary provided within this +component. Find sources and license at https://github.com/Seldaek/hidden-input. diff --git a/www/multitube/vendor/symfony/console/Resources/bin/hiddeninput.exe b/www/multitube/vendor/symfony/console/Resources/bin/hiddeninput.exe new file mode 100644 index 0000000..c8cf65e Binary files /dev/null and b/www/multitube/vendor/symfony/console/Resources/bin/hiddeninput.exe differ diff --git a/www/multitube/vendor/symfony/console/Style/OutputStyle.php b/www/multitube/vendor/symfony/console/Style/OutputStyle.php new file mode 100644 index 0000000..14d2d60 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Style/OutputStyle.php @@ -0,0 +1,155 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +use Symfony\Component\Console\Formatter\OutputFormatterInterface; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Output\OutputInterface; + +/** + * Decorates output to add console style guide helpers. + * + * @author Kevin Bond + */ +abstract class OutputStyle implements OutputInterface, StyleInterface +{ + private $output; + + public function __construct(OutputInterface $output) + { + $this->output = $output; + } + + /** + * {@inheritdoc} + */ + public function newLine($count = 1) + { + $this->output->write(str_repeat(\PHP_EOL, $count)); + } + + /** + * @param int $max + * + * @return ProgressBar + */ + public function createProgressBar($max = 0) + { + return new ProgressBar($this->output, $max); + } + + /** + * {@inheritdoc} + */ + public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) + { + $this->output->write($messages, $newline, $type); + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, $type = self::OUTPUT_NORMAL) + { + $this->output->writeln($messages, $type); + } + + /** + * {@inheritdoc} + */ + public function setVerbosity($level) + { + $this->output->setVerbosity($level); + } + + /** + * {@inheritdoc} + */ + public function getVerbosity() + { + return $this->output->getVerbosity(); + } + + /** + * {@inheritdoc} + */ + public function setDecorated($decorated) + { + $this->output->setDecorated($decorated); + } + + /** + * {@inheritdoc} + */ + public function isDecorated() + { + return $this->output->isDecorated(); + } + + /** + * {@inheritdoc} + */ + public function setFormatter(OutputFormatterInterface $formatter) + { + $this->output->setFormatter($formatter); + } + + /** + * {@inheritdoc} + */ + public function getFormatter() + { + return $this->output->getFormatter(); + } + + /** + * {@inheritdoc} + */ + public function isQuiet() + { + return $this->output->isQuiet(); + } + + /** + * {@inheritdoc} + */ + public function isVerbose() + { + return $this->output->isVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isVeryVerbose() + { + return $this->output->isVeryVerbose(); + } + + /** + * {@inheritdoc} + */ + public function isDebug() + { + return $this->output->isDebug(); + } + + protected function getErrorOutput() + { + if (!$this->output instanceof ConsoleOutputInterface) { + return $this->output; + } + + return $this->output->getErrorOutput(); + } +} diff --git a/www/multitube/vendor/symfony/console/Style/StyleInterface.php b/www/multitube/vendor/symfony/console/Style/StyleInterface.php new file mode 100644 index 0000000..3b5b8af --- /dev/null +++ b/www/multitube/vendor/symfony/console/Style/StyleInterface.php @@ -0,0 +1,153 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +/** + * Output style helpers. + * + * @author Kevin Bond + */ +interface StyleInterface +{ + /** + * Formats a command title. + * + * @param string $message + */ + public function title($message); + + /** + * Formats a section title. + * + * @param string $message + */ + public function section($message); + + /** + * Formats a list. + */ + public function listing(array $elements); + + /** + * Formats informational text. + * + * @param string|array $message + */ + public function text($message); + + /** + * Formats a success result bar. + * + * @param string|array $message + */ + public function success($message); + + /** + * Formats an error result bar. + * + * @param string|array $message + */ + public function error($message); + + /** + * Formats an warning result bar. + * + * @param string|array $message + */ + public function warning($message); + + /** + * Formats a note admonition. + * + * @param string|array $message + */ + public function note($message); + + /** + * Formats a caution admonition. + * + * @param string|array $message + */ + public function caution($message); + + /** + * Formats a table. + */ + public function table(array $headers, array $rows); + + /** + * Asks a question. + * + * @param string $question + * @param string|null $default + * @param callable|null $validator + * + * @return mixed + */ + public function ask($question, $default = null, $validator = null); + + /** + * Asks a question with the user input hidden. + * + * @param string $question + * @param callable|null $validator + * + * @return mixed + */ + public function askHidden($question, $validator = null); + + /** + * Asks for confirmation. + * + * @param string $question + * @param bool $default + * + * @return bool + */ + public function confirm($question, $default = true); + + /** + * Asks a choice question. + * + * @param string $question + * @param string|int|null $default + * + * @return mixed + */ + public function choice($question, array $choices, $default = null); + + /** + * Add newline(s). + * + * @param int $count The number of newlines + */ + public function newLine($count = 1); + + /** + * Starts the progress output. + * + * @param int $max Maximum steps (0 if unknown) + */ + public function progressStart($max = 0); + + /** + * Advances the progress output X steps. + * + * @param int $step Number of steps to advance + */ + public function progressAdvance($step = 1); + + /** + * Finishes the progress output. + */ + public function progressFinish(); +} diff --git a/www/multitube/vendor/symfony/console/Style/SymfonyStyle.php b/www/multitube/vendor/symfony/console/Style/SymfonyStyle.php new file mode 100644 index 0000000..4d83779 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Style/SymfonyStyle.php @@ -0,0 +1,431 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Style; + +use Symfony\Component\Console\Exception\RuntimeException; +use Symfony\Component\Console\Formatter\OutputFormatter; +use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Helper\SymfonyQuestionHelper; +use Symfony\Component\Console\Helper\Table; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Question\ChoiceQuestion; +use Symfony\Component\Console\Question\ConfirmationQuestion; +use Symfony\Component\Console\Question\Question; +use Symfony\Component\Console\Terminal; + +/** + * Output decorator helpers for the Symfony Style Guide. + * + * @author Kevin Bond + */ +class SymfonyStyle extends OutputStyle +{ + const MAX_LINE_LENGTH = 120; + + private $input; + private $questionHelper; + private $progressBar; + private $lineLength; + private $bufferedOutput; + + public function __construct(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter()); + // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not. + $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH; + $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH); + + parent::__construct($output); + } + + /** + * Formats a message as a block of text. + * + * @param string|array $messages The message to write in the block + * @param string|null $type The block type (added in [] on first line) + * @param string|null $style The style to apply to the whole block + * @param string $prefix The prefix for the block + * @param bool $padding Whether to add vertical padding + * @param bool $escape Whether to escape the message + */ + public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = true) + { + $messages = \is_array($messages) ? array_values($messages) : [$messages]; + + $this->autoPrependBlock(); + $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape)); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function title($message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function section($message) + { + $this->autoPrependBlock(); + $this->writeln([ + sprintf('%s', OutputFormatter::escapeTrailingBackslash($message)), + sprintf('%s', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))), + ]); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function listing(array $elements) + { + $this->autoPrependText(); + $elements = array_map(function ($element) { + return sprintf(' * %s', $element); + }, $elements); + + $this->writeln($elements); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function text($message) + { + $this->autoPrependText(); + + $messages = \is_array($message) ? array_values($message) : [$message]; + foreach ($messages as $message) { + $this->writeln(sprintf(' %s', $message)); + } + } + + /** + * Formats a command comment. + * + * @param string|array $message + */ + public function comment($message) + { + $this->block($message, null, null, ' // ', false, false); + } + + /** + * {@inheritdoc} + */ + public function success($message) + { + $this->block($message, 'OK', 'fg=black;bg=green', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function error($message) + { + $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function warning($message) + { + $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true); + } + + /** + * {@inheritdoc} + */ + public function note($message) + { + $this->block($message, 'NOTE', 'fg=yellow', ' ! '); + } + + /** + * {@inheritdoc} + */ + public function caution($message) + { + $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true); + } + + /** + * {@inheritdoc} + */ + public function table(array $headers, array $rows) + { + $style = clone Table::getStyleDefinition('symfony-style-guide'); + $style->setCellHeaderFormat('%s'); + + $table = new Table($this); + $table->setHeaders($headers); + $table->setRows($rows); + $table->setStyle($style); + + $table->render(); + $this->newLine(); + } + + /** + * {@inheritdoc} + */ + public function ask($question, $default = null, $validator = null) + { + $question = new Question($question, $default); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function askHidden($question, $validator = null) + { + $question = new Question($question); + + $question->setHidden(true); + $question->setValidator($validator); + + return $this->askQuestion($question); + } + + /** + * {@inheritdoc} + */ + public function confirm($question, $default = true) + { + return $this->askQuestion(new ConfirmationQuestion($question, $default)); + } + + /** + * {@inheritdoc} + */ + public function choice($question, array $choices, $default = null) + { + if (null !== $default) { + $values = array_flip($choices); + $default = isset($values[$default]) ? $values[$default] : $default; + } + + return $this->askQuestion(new ChoiceQuestion($question, $choices, $default)); + } + + /** + * {@inheritdoc} + */ + public function progressStart($max = 0) + { + $this->progressBar = $this->createProgressBar($max); + $this->progressBar->start(); + } + + /** + * {@inheritdoc} + */ + public function progressAdvance($step = 1) + { + $this->getProgressBar()->advance($step); + } + + /** + * {@inheritdoc} + */ + public function progressFinish() + { + $this->getProgressBar()->finish(); + $this->newLine(2); + $this->progressBar = null; + } + + /** + * {@inheritdoc} + */ + public function createProgressBar($max = 0) + { + $progressBar = parent::createProgressBar($max); + + if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) { + $progressBar->setEmptyBarCharacter('░'); // light shade character \u2591 + $progressBar->setProgressCharacter(''); + $progressBar->setBarCharacter('▓'); // dark shade character \u2593 + } + + return $progressBar; + } + + /** + * @return mixed + */ + public function askQuestion(Question $question) + { + if ($this->input->isInteractive()) { + $this->autoPrependBlock(); + } + + if (!$this->questionHelper) { + $this->questionHelper = new SymfonyQuestionHelper(); + } + + $answer = $this->questionHelper->ask($this->input, $this, $question); + + if ($this->input->isInteractive()) { + $this->newLine(); + $this->bufferedOutput->write("\n"); + } + + return $answer; + } + + /** + * {@inheritdoc} + */ + public function writeln($messages, $type = self::OUTPUT_NORMAL) + { + parent::writeln($messages, $type); + $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type); + } + + /** + * {@inheritdoc} + */ + public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL) + { + parent::write($messages, $newline, $type); + $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type); + } + + /** + * {@inheritdoc} + */ + public function newLine($count = 1) + { + parent::newLine($count); + $this->bufferedOutput->write(str_repeat("\n", $count)); + } + + /** + * Returns a new instance which makes use of stderr if available. + * + * @return self + */ + public function getErrorStyle() + { + return new self($this->input, $this->getErrorOutput()); + } + + /** + * @return ProgressBar + */ + private function getProgressBar() + { + if (!$this->progressBar) { + throw new RuntimeException('The ProgressBar is not started.'); + } + + return $this->progressBar; + } + + private function autoPrependBlock() + { + $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); + + if (!isset($chars[0])) { + $this->newLine(); //empty history, so we should start with a new line. + + return; + } + //Prepend new line for each non LF chars (This means no blank line was output before) + $this->newLine(2 - substr_count($chars, "\n")); + } + + private function autoPrependText() + { + $fetched = $this->bufferedOutput->fetch(); + //Prepend new line if last char isn't EOL: + if ("\n" !== substr($fetched, -1)) { + $this->newLine(); + } + } + + private function reduceBuffer($messages) + { + // We need to know if the two last chars are PHP_EOL + // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer + return array_map(function ($value) { + return substr($value, -4); + }, array_merge([$this->bufferedOutput->fetch()], (array) $messages)); + } + + private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false) + { + $indentLength = 0; + $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); + $lines = []; + + if (null !== $type) { + $type = sprintf('[%s] ', $type); + $indentLength = \strlen($type); + $lineIndentation = str_repeat(' ', $indentLength); + } + + // wrap and add newlines for each element + foreach ($messages as $key => $message) { + if ($escape) { + $message = OutputFormatter::escape($message); + } + + $lines = array_merge($lines, explode(\PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, \PHP_EOL, true))); + + if (\count($messages) > 1 && $key < \count($messages) - 1) { + $lines[] = ''; + } + } + + $firstLineIndex = 0; + if ($padding && $this->isDecorated()) { + $firstLineIndex = 1; + array_unshift($lines, ''); + $lines[] = ''; + } + + foreach ($lines as $i => &$line) { + if (null !== $type) { + $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line; + } + + $line = $prefix.$line; + $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line)); + + if ($style) { + $line = sprintf('<%s>%s', $style, $line); + } + } + + return $lines; + } +} diff --git a/www/multitube/vendor/symfony/console/Terminal.php b/www/multitube/vendor/symfony/console/Terminal.php new file mode 100644 index 0000000..774c5f7 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Terminal.php @@ -0,0 +1,181 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console; + +class Terminal +{ + private static $width; + private static $height; + private static $stty; + + /** + * Gets the terminal width. + * + * @return int + */ + public function getWidth() + { + $width = getenv('COLUMNS'); + if (false !== $width) { + return (int) trim($width); + } + + if (null === self::$width) { + self::initDimensions(); + } + + return self::$width ?: 80; + } + + /** + * Gets the terminal height. + * + * @return int + */ + public function getHeight() + { + $height = getenv('LINES'); + if (false !== $height) { + return (int) trim($height); + } + + if (null === self::$height) { + self::initDimensions(); + } + + return self::$height ?: 50; + } + + /** + * @internal + * + * @return bool + */ + public static function hasSttyAvailable() + { + if (null !== self::$stty) { + return self::$stty; + } + + // skip check if exec function is disabled + if (!\function_exists('exec')) { + return false; + } + + exec('stty 2>&1', $output, $exitcode); + + return self::$stty = 0 === $exitcode; + } + + private static function initDimensions() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + if (preg_match('/^(\d+)x(\d+)(?: \((\d+)x(\d+)\))?$/', trim(getenv('ANSICON')), $matches)) { + // extract [w, H] from "wxh (WxH)" + // or [w, h] from "wxh" + self::$width = (int) $matches[1]; + self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2]; + } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) { + // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash) + // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT + self::initDimensionsUsingStty(); + } elseif (null !== $dimensions = self::getConsoleMode()) { + // extract [w, h] from "wxh" + self::$width = (int) $dimensions[0]; + self::$height = (int) $dimensions[1]; + } + } else { + self::initDimensionsUsingStty(); + } + } + + /** + * Returns whether STDOUT has vt100 support (some Windows 10+ configurations). + */ + private static function hasVt100Support() + { + return \function_exists('sapi_windows_vt100_support') && sapi_windows_vt100_support(fopen('php://stdout', 'w')); + } + + /** + * Initializes dimensions using the output of an stty columns line. + */ + private static function initDimensionsUsingStty() + { + if ($sttyString = self::getSttyColumns()) { + if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) { + // extract [w, h] from "rows h; columns w;" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } elseif (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) { + // extract [w, h] from "; h rows; w columns" + self::$width = (int) $matches[2]; + self::$height = (int) $matches[1]; + } + } + } + + /** + * Runs and parses mode CON if it's available, suppressing any error output. + * + * @return int[]|null An array composed of the width and the height or null if it could not be parsed + */ + private static function getConsoleMode() + { + $info = self::readFromProcess('mode CON'); + + if (null === $info || !preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) { + return null; + } + + return [(int) $matches[2], (int) $matches[1]]; + } + + /** + * Runs and parses stty -a if it's available, suppressing any error output. + * + * @return string|null + */ + private static function getSttyColumns() + { + return self::readFromProcess('stty -a | grep columns'); + } + + /** + * @param string $command + * + * @return string|null + */ + private static function readFromProcess($command) + { + if (!\function_exists('proc_open')) { + return null; + } + + $descriptorspec = [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $process = proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => true]); + if (!\is_resource($process)) { + return null; + } + + $info = stream_get_contents($pipes[1]); + fclose($pipes[1]); + fclose($pipes[2]); + proc_close($process); + + return $info; + } +} diff --git a/www/multitube/vendor/symfony/console/Tester/ApplicationTester.php b/www/multitube/vendor/symfony/console/Tester/ApplicationTester.php new file mode 100644 index 0000000..355b07b --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tester/ApplicationTester.php @@ -0,0 +1,176 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; + +/** + * Eases the testing of console applications. + * + * When testing an application, don't forget to disable the auto exit flag: + * + * $application = new Application(); + * $application->setAutoExit(false); + * + * @author Fabien Potencier + */ +class ApplicationTester +{ + private $application; + private $input; + private $statusCode; + /** + * @var OutputInterface + */ + private $output; + private $captureStreamsIndependently = false; + + public function __construct(Application $application) + { + $this->application = $application; + } + + /** + * Executes the application. + * + * Available options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * * capture_stderr_separately: Make output of stdOut and stdErr separately available + * + * @param array $input An array of arguments and options + * @param array $options An array of options + * + * @return int The command exit code + */ + public function run(array $input, $options = []) + { + $this->input = new ArrayInput($input); + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; + if (!$this->captureStreamsIndependently) { + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + if (isset($options['decorated'])) { + $this->output->setDecorated($options['decorated']); + } + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + } else { + $this->output = new ConsoleOutput( + isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, + isset($options['decorated']) ? $options['decorated'] : null + ); + + $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); + $errorOutput->setFormatter($this->output->getFormatter()); + $errorOutput->setVerbosity($this->output->getVerbosity()); + $errorOutput->setDecorated($this->output->isDecorated()); + + $reflectedOutput = new \ReflectionObject($this->output); + $strErrProperty = $reflectedOutput->getProperty('stderr'); + $strErrProperty->setAccessible(true); + $strErrProperty->setValue($this->output, $errorOutput); + + $reflectedParent = $reflectedOutput->getParentClass(); + $streamProperty = $reflectedParent->getProperty('stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); + } + + return $this->statusCode = $this->application->run($this->input, $this->output); + } + + /** + * Gets the display returned by the last execution of the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string The display + */ + public function getDisplay($normalize = false) + { + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the output written to STDERR by the application. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string + */ + public function getErrorOutput($normalize = false) + { + if (!$this->captureStreamsIndependently) { + throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); + } + + rewind($this->output->getErrorOutput()->getStream()); + + $display = stream_get_contents($this->output->getErrorOutput()->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the application. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the application. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } + + /** + * Gets the status code returned by the last execution of the application. + * + * @return int The status code + */ + public function getStatusCode() + { + return $this->statusCode; + } +} diff --git a/www/multitube/vendor/symfony/console/Tester/CommandTester.php b/www/multitube/vendor/symfony/console/Tester/CommandTester.php new file mode 100644 index 0000000..1229894 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tester/CommandTester.php @@ -0,0 +1,162 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tester; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; + +/** + * Eases the testing of console commands. + * + * @author Fabien Potencier + * @author Robin Chalas + */ +class CommandTester +{ + private $command; + private $input; + private $output; + private $inputs = []; + private $statusCode; + + public function __construct(Command $command) + { + $this->command = $command; + } + + /** + * Executes the command. + * + * Available execution options: + * + * * interactive: Sets the input interactive flag + * * decorated: Sets the output decorated flag + * * verbosity: Sets the output verbosity flag + * + * @param array $input An array of command arguments and options + * @param array $options An array of execution options + * + * @return int The command exit code + */ + public function execute(array $input, array $options = []) + { + // set the command name automatically if the application requires + // this argument and no command name was passed + if (!isset($input['command']) + && (null !== $application = $this->command->getApplication()) + && $application->getDefinition()->hasArgument('command') + ) { + $input = array_merge(['command' => $this->command->getName()], $input); + } + + $this->input = new ArrayInput($input); + // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN. + $this->input->setStream(self::createStream($this->inputs)); + + if (isset($options['interactive'])) { + $this->input->setInteractive($options['interactive']); + } + + $this->output = new StreamOutput(fopen('php://memory', 'w', false)); + $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false); + if (isset($options['verbosity'])) { + $this->output->setVerbosity($options['verbosity']); + } + + return $this->statusCode = $this->command->run($this->input, $this->output); + } + + /** + * Gets the display returned by the last execution of the command. + * + * @param bool $normalize Whether to normalize end of lines to \n or not + * + * @return string The display + */ + public function getDisplay($normalize = false) + { + if (null === $this->output) { + throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?'); + } + + rewind($this->output->getStream()); + + $display = stream_get_contents($this->output->getStream()); + + if ($normalize) { + $display = str_replace(\PHP_EOL, "\n", $display); + } + + return $display; + } + + /** + * Gets the input instance used by the last execution of the command. + * + * @return InputInterface The current input instance + */ + public function getInput() + { + return $this->input; + } + + /** + * Gets the output instance used by the last execution of the command. + * + * @return OutputInterface The current output instance + */ + public function getOutput() + { + return $this->output; + } + + /** + * Gets the status code returned by the last execution of the application. + * + * @return int The status code + */ + public function getStatusCode() + { + return $this->statusCode; + } + + /** + * Sets the user inputs. + * + * @param array $inputs An array of strings representing each input + * passed to the command input stream + * + * @return CommandTester + */ + public function setInputs(array $inputs) + { + $this->inputs = $inputs; + + return $this; + } + + private static function createStream(array $inputs) + { + $stream = fopen('php://memory', 'r+', false); + + foreach ($inputs as $input) { + fwrite($stream, $input.\PHP_EOL); + } + + rewind($stream); + + return $stream; + } +} diff --git a/www/multitube/vendor/symfony/console/Tests/ApplicationTest.php b/www/multitube/vendor/symfony/console/Tests/ApplicationTest.php new file mode 100644 index 0000000..16d856c --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tests/ApplicationTest.php @@ -0,0 +1,1786 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; +use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\Console\Event\ConsoleCommandEvent; +use Symfony\Component\Console\Event\ConsoleErrorEvent; +use Symfony\Component\Console\Event\ConsoleExceptionEvent; +use Symfony\Component\Console\Event\ConsoleTerminateEvent; +use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Helper\HelperSet; +use Symfony\Component\Console\Input\ArgvInput; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Console\Output\Output; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Output\StreamOutput; +use Symfony\Component\Console\Tester\ApplicationTester; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\EventDispatcher\EventDispatcher; + +class ApplicationTest extends TestCase +{ + protected static $fixturesPath; + + private $colSize; + + protected function setUp() + { + $this->colSize = getenv('COLUMNS'); + } + + protected function tearDown() + { + putenv($this->colSize ? 'COLUMNS='.$this->colSize : 'COLUMNS'); + putenv('SHELL_VERBOSITY'); + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } + + public static function setUpBeforeClass() + { + self::$fixturesPath = realpath(__DIR__.'/Fixtures/'); + require_once self::$fixturesPath.'/FooCommand.php'; + require_once self::$fixturesPath.'/FooOptCommand.php'; + require_once self::$fixturesPath.'/Foo1Command.php'; + require_once self::$fixturesPath.'/Foo2Command.php'; + require_once self::$fixturesPath.'/Foo3Command.php'; + require_once self::$fixturesPath.'/Foo4Command.php'; + require_once self::$fixturesPath.'/Foo5Command.php'; + require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php'; + require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php'; + require_once self::$fixturesPath.'/FoobarCommand.php'; + require_once self::$fixturesPath.'/BarBucCommand.php'; + require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; + require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; + require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering.php'; + require_once self::$fixturesPath.'/TestAmbiguousCommandRegistering2.php'; + require_once self::$fixturesPath.'/FooHiddenCommand.php'; + } + + protected function normalizeLineBreaks($text) + { + return str_replace(\PHP_EOL, "\n", $text); + } + + /** + * Replaces the dynamic placeholders of the command help text with a static version. + * The placeholder %command.full_name% includes the script path that is not predictable + * and can not be tested against. + */ + protected function ensureStaticCommandHelp(Application $application) + { + foreach ($application->all() as $command) { + $command->setHelp(str_replace('%command.full_name%', 'app/console %command.name%', $command->getHelp())); + } + } + + public function testConstructor() + { + $application = new Application('foo', 'bar'); + $this->assertEquals('foo', $application->getName(), '__construct() takes the application name as its first argument'); + $this->assertEquals('bar', $application->getVersion(), '__construct() takes the application version as its second argument'); + $this->assertEquals(['help', 'list'], array_keys($application->all()), '__construct() registered the help and list commands by default'); + } + + public function testSetGetName() + { + $application = new Application(); + $application->setName('foo'); + $this->assertEquals('foo', $application->getName(), '->setName() sets the name of the application'); + } + + public function testSetGetVersion() + { + $application = new Application(); + $application->setVersion('bar'); + $this->assertEquals('bar', $application->getVersion(), '->setVersion() sets the version of the application'); + } + + public function testGetLongVersion() + { + $application = new Application('foo', 'bar'); + $this->assertEquals('foo bar', $application->getLongVersion(), '->getLongVersion() returns the long version of the application'); + } + + public function testHelp() + { + $application = new Application(); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_gethelp.txt', $this->normalizeLineBreaks($application->getHelp()), '->getHelp() returns a help message'); + } + + public function testAll() + { + $application = new Application(); + $commands = $application->all(); + $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); + + $application->add(new \FooCommand()); + $commands = $application->all('foo'); + $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); + } + + public function testAllWithCommandLoader() + { + $application = new Application(); + $commands = $application->all(); + $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); + + $application->add(new \FooCommand()); + $commands = $application->all('foo'); + $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); + + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo:bar1' => function () { return new \Foo1Command(); }, + ])); + $commands = $application->all('foo'); + $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); + $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); + $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands'); + } + + public function testRegister() + { + $application = new Application(); + $command = $application->register('foo'); + $this->assertEquals('foo', $command->getName(), '->register() registers a new command'); + } + + public function testRegisterAmbiguous() + { + $code = function (InputInterface $input, OutputInterface $output) { + $output->writeln('It works!'); + }; + + $application = new Application(); + $application->setAutoExit(false); + $application + ->register('test-foo') + ->setAliases(['test']) + ->setCode($code); + + $application + ->register('test-bar') + ->setCode($code); + + $tester = new ApplicationTester($application); + $tester->run(['test']); + $this->assertStringContainsString('It works!', $tester->getDisplay(true)); + } + + public function testAdd() + { + $application = new Application(); + $application->add($foo = new \FooCommand()); + $commands = $application->all(); + $this->assertEquals($foo, $commands['foo:bar'], '->add() registers a command'); + + $application = new Application(); + $application->addCommands([$foo = new \FooCommand(), $foo1 = new \Foo1Command()]); + $commands = $application->all(); + $this->assertEquals([$foo, $foo1], [$commands['foo:bar'], $commands['foo:bar1']], '->addCommands() registers an array of commands'); + } + + public function testAddCommandWithEmptyConstructor() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('Command class "Foo5Command" is not correctly initialized. You probably forgot to call the parent constructor.'); + $application = new Application(); + $application->add(new \Foo5Command()); + } + + public function testHasGet() + { + $application = new Application(); + $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); + $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); + + $application->add($foo = new \FooCommand()); + $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); + + $application = new Application(); + $application->add($foo = new \FooCommand()); + // simulate --help + $r = new \ReflectionObject($application); + $p = $r->getProperty('wantHelps'); + $p->setAccessible(true); + $p->setValue($application, true); + $command = $application->get('foo:bar'); + $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input'); + } + + public function testHasGetWithCommandLoader() + { + $application = new Application(); + $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); + $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); + + $application->add($foo = new \FooCommand()); + $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); + + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo:bar1' => function () { return new \Foo1Command(); }, + ])); + + $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader'); + $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader'); + $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader'); + $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader'); + $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader'); + } + + public function testSilentHelp() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $tester = new ApplicationTester($application); + $tester->run(['-h' => true, '-q' => true], ['decorated' => false]); + + $this->assertEmpty($tester->getDisplay(true)); + } + + public function testGetInvalidCommand() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('The command "foofoo" does not exist.'); + $application = new Application(); + $application->get('foofoo'); + } + + public function testGetNamespaces() + { + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $this->assertEquals(['foo'], $application->getNamespaces(), '->getNamespaces() returns an array of unique used namespaces'); + } + + public function testFindNamespace() + { + $application = new Application(); + $application->add(new \FooCommand()); + $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); + $this->assertEquals('foo', $application->findNamespace('f'), '->findNamespace() finds a namespace given an abbreviation'); + $application->add(new \Foo2Command()); + $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns the given namespace if it exists'); + } + + public function testFindNamespaceWithSubnamespaces() + { + $application = new Application(); + $application->add(new \FooSubnamespaced1Command()); + $application->add(new \FooSubnamespaced2Command()); + $this->assertEquals('foo', $application->findNamespace('foo'), '->findNamespace() returns commands even if the commands are only contained in subnamespaces'); + } + + public function testFindAmbiguousNamespace() + { + $application = new Application(); + $application->add(new \BarBucCommand()); + $application->add(new \FooCommand()); + $application->add(new \Foo2Command()); + + $expectedMsg = "The namespace \"f\" is ambiguous.\nDid you mean one of these?\n foo\n foo1"; + + $this->expectException(CommandNotFoundException::class); + $this->expectExceptionMessage($expectedMsg); + + $application->findNamespace('f'); + } + + public function testFindNonAmbiguous() + { + $application = new Application(); + $application->add(new \TestAmbiguousCommandRegistering()); + $application->add(new \TestAmbiguousCommandRegistering2()); + $this->assertEquals('test-ambiguous', $application->find('test')->getName()); + } + + public function testFindInvalidNamespace() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('There are no commands defined in the "bar" namespace.'); + $application = new Application(); + $application->findNamespace('bar'); + } + + public function testFindUniqueNameButNamespaceName() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('Command "foo1" is not defined'); + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + + $application->find($commandName = 'foo1'); + } + + public function testFind() + { + $application = new Application(); + $application->add(new \FooCommand()); + + $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); + $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); + } + + public function testFindCaseSensitiveFirst() + { + $application = new Application(); + $application->add(new \FooSameCaseUppercaseCommand()); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case'); + } + + public function testFindCaseInsensitiveAsFallback() + { + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity'); + } + + public function testFindCaseInsensitiveSuggestions() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('Command "FoO:BaR" is ambiguous'); + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + $application->add(new \FooSameCaseUppercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity'); + } + + public function testFindWithCommandLoader() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo:bar' => $f = function () { return new \FooCommand(); }, + ])); + + $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); + $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); + } + + /** + * @dataProvider provideAmbiguousAbbreviations + */ + public function testFindWithAmbiguousAbbreviations($abbreviation, $expectedExceptionMessage) + { + putenv('COLUMNS=120'); + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage($expectedExceptionMessage); + + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + + $application->find($abbreviation); + } + + public function provideAmbiguousAbbreviations() + { + return [ + ['f', 'Command "f" is not defined.'], + [ + 'a', + "Command \"a\" is ambiguous.\nDid you mean one of these?\n". + " afoobar The foo:bar command\n". + " afoobar1 The foo:bar1 command\n". + ' afoobar2 The foo1:bar command', + ], + [ + 'foo:b', + "Command \"foo:b\" is ambiguous.\nDid you mean one of these?\n". + " foo:bar The foo:bar command\n". + " foo:bar1 The foo:bar1 command\n". + ' foo1:bar The foo1:bar command', + ], + ]; + } + + public function testFindCommandEqualNamespace() + { + $application = new Application(); + $application->add(new \Foo3Command()); + $application->add(new \Foo4Command()); + + $this->assertInstanceOf('Foo3Command', $application->find('foo3:bar'), '->find() returns the good command even if a namespace has same name'); + $this->assertInstanceOf('Foo4Command', $application->find('foo3:bar:toh'), '->find() returns a command even if its namespace equals another command name'); + } + + public function testFindCommandWithAmbiguousNamespacesButUniqueName() + { + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \FoobarCommand()); + + $this->assertInstanceOf('FoobarCommand', $application->find('f:f')); + } + + public function testFindCommandWithMissingNamespace() + { + $application = new Application(); + $application->add(new \Foo4Command()); + + $this->assertInstanceOf('Foo4Command', $application->find('f::t')); + } + + /** + * @dataProvider provideInvalidCommandNamesSingle + */ + public function testFindAlternativeExceptionMessageSingle($name) + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('Did you mean this'); + $application = new Application(); + $application->add(new \Foo3Command()); + $application->find($name); + } + + public function provideInvalidCommandNamesSingle() + { + return [ + ['foo3:barr'], + ['fooo3:bar'], + ]; + } + + public function testFindAlternativeExceptionMessageMultiple() + { + putenv('COLUMNS=120'); + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + + // Command + plural + try { + $application->find('foo:baR'); + $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression('/foo1:bar/', $e->getMessage()); + $this->assertMatchesRegularExpression('/foo:bar/', $e->getMessage()); + } + + // Namespace + plural + try { + $application->find('foo2:bar'); + $this->fail('->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression('/Did you mean one of these/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression('/foo1/', $e->getMessage()); + } + + $application->add(new \Foo3Command()); + $application->add(new \Foo4Command()); + + // Subnamespace + plural + try { + $application->find('foo3:'); + $this->fail('->find() should throw an Symfony\Component\Console\Exception\CommandNotFoundException if a command is ambiguous because of a subnamespace, with alternatives'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e); + $this->assertMatchesRegularExpression('/foo3:bar/', $e->getMessage()); + $this->assertMatchesRegularExpression('/foo3:bar:toh/', $e->getMessage()); + } + } + + public function testFindAlternativeCommands() + { + $application = new Application(); + + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + + try { + $application->find($commandName = 'Unknown command'); + $this->fail('->find() throws a CommandNotFoundException if command does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); + $this->assertSame([], $e->getAlternatives()); + $this->assertEquals(sprintf('Command "%s" is not defined.', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without alternatives'); + } + + // Test if "bar1" command throw a "CommandNotFoundException" and does not contain + // "foo:bar" as alternative because "bar1" is too far from "foo:bar" + try { + $application->find($commandName = 'bar1'); + $this->fail('->find() throws a CommandNotFoundException if command does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command does not exist'); + $this->assertSame(['afoobar1', 'foo:bar1'], $e->getAlternatives()); + $this->assertMatchesRegularExpression(sprintf('/Command "%s" is not defined./', $commandName), $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternatives'); + $this->assertMatchesRegularExpression('/afoobar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "afoobar1"'); + $this->assertMatchesRegularExpression('/foo:bar1/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, with alternative : "foo:bar1"'); + $this->assertDoesNotMatchRegularExpression('/foo:bar(?!1)/', $e->getMessage(), '->find() throws a CommandNotFoundException if command does not exist, without "foo:bar" alternative'); + } + } + + public function testFindAlternativeCommandsWithAnAlias() + { + $fooCommand = new \FooCommand(); + $fooCommand->setAliases(['foo2']); + + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo3' => static function () use ($fooCommand) { return $fooCommand; }, + ])); + $application->add($fooCommand); + + $result = $application->find('foo'); + + $this->assertSame($fooCommand, $result); + } + + public function testFindAlternativeNamespace() + { + $application = new Application(); + + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + $application->add(new \Foo3Command()); + + try { + $application->find('Unknown-namespace:Unknown-command'); + $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); + $this->assertSame([], $e->getAlternatives()); + $this->assertEquals('There are no commands defined in the "Unknown-namespace" namespace.', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, without alternatives'); + } + + try { + $application->find('foo2:command'); + $this->fail('->find() throws a CommandNotFoundException if namespace does not exist'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if namespace does not exist'); + $this->assertCount(3, $e->getAlternatives()); + $this->assertContains('foo', $e->getAlternatives()); + $this->assertContains('foo1', $e->getAlternatives()); + $this->assertContains('foo3', $e->getAlternatives()); + $this->assertMatchesRegularExpression('/There are no commands defined in the "foo2" namespace./', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative'); + $this->assertMatchesRegularExpression('/foo/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo"'); + $this->assertMatchesRegularExpression('/foo1/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo1"'); + $this->assertMatchesRegularExpression('/foo3/', $e->getMessage(), '->find() throws a CommandNotFoundException if namespace does not exist, with alternative : "foo3"'); + } + } + + public function testFindAlternativesOutput() + { + $application = new Application(); + + $application->add(new \FooCommand()); + $application->add(new \Foo1Command()); + $application->add(new \Foo2Command()); + $application->add(new \Foo3Command()); + $application->add(new \FooHiddenCommand()); + + $expectedAlternatives = [ + 'afoobar', + 'afoobar1', + 'afoobar2', + 'foo1:bar', + 'foo3:bar', + 'foo:bar', + 'foo:bar1', + ]; + + try { + $application->find('foo'); + $this->fail('->find() throws a CommandNotFoundException if command is not defined'); + } catch (\Exception $e) { + $this->assertInstanceOf('Symfony\Component\Console\Exception\CommandNotFoundException', $e, '->find() throws a CommandNotFoundException if command is not defined'); + $this->assertSame($expectedAlternatives, $e->getAlternatives()); + + $this->assertMatchesRegularExpression('/Command "foo" is not defined\..*Did you mean one of these\?.*/Ums', $e->getMessage()); + } + } + + public function testFindNamespaceDoesNotFailOnDeepSimilarNamespaces() + { + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['getNamespaces'])->getMock(); + $application->expects($this->once()) + ->method('getNamespaces') + ->willReturn(['foo:sublong', 'bar:sub']); + + $this->assertEquals('foo:sublong', $application->findNamespace('f:sub')); + } + + public function testFindWithDoubleColonInNameThrowsException() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $this->expectExceptionMessage('Command "foo::bar" is not defined.'); + $application = new Application(); + $application->add(new \FooCommand()); + $application->add(new \Foo4Command()); + $application->find('foo::bar'); + } + + public function testSetCatchExceptions() + { + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=120'); + $tester = new ApplicationTester($application); + + $application->setCatchExceptions(true); + $this->assertTrue($application->areExceptionsCaught()); + + $tester->run(['command' => 'foo'], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getDisplay(true), '->setCatchExceptions() sets the catch exception flag'); + + $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->setCatchExceptions() sets the catch exception flag'); + $this->assertSame('', $tester->getDisplay(true)); + + $application->setCatchExceptions(false); + try { + $tester->run(['command' => 'foo'], ['decorated' => false]); + $this->fail('->setCatchExceptions() sets the catch exception flag'); + } catch (\Exception $e) { + $this->assertInstanceOf('\Exception', $e, '->setCatchExceptions() sets the catch exception flag'); + $this->assertEquals('Command "foo" is not defined.', $e->getMessage(), '->setCatchExceptions() sets the catch exception flag'); + } + } + + public function testAutoExitSetting() + { + $application = new Application(); + $this->assertTrue($application->isAutoExitEnabled()); + + $application->setAutoExit(false); + $this->assertFalse($application->isAutoExitEnabled()); + } + + public function testRenderException() + { + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=120'); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exception'); + + $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE, 'capture_stderr_separately' => true]); + $this->assertStringContainsString('Exception trace', $tester->getErrorOutput(), '->renderException() renders a pretty exception with a stack trace when verbosity is verbose'); + + $tester->run(['command' => 'list', '--foo' => true], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception2.txt', $tester->getErrorOutput(true), '->renderException() renders the command synopsis when an exception occurs in the context of a command'); + + $application->add(new \Foo3Command()); + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo3:bar'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $tester->run(['command' => 'foo3:bar'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE]); + $this->assertMatchesRegularExpression('/\[Exception\]\s*First exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is default and verbosity is verbose'); + $this->assertMatchesRegularExpression('/\[Exception\]\s*Second exception/', $tester->getDisplay(), '->renderException() renders a pretty exception without code exception when code exception is 0 and verbosity is verbose'); + $this->assertMatchesRegularExpression('/\[Exception \(404\)\]\s*Third exception/', $tester->getDisplay(), '->renderException() renders a pretty exception with code exception when code exception is 404 and verbosity is verbose'); + + $tester->run(['command' => 'foo3:bar'], ['decorated' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getDisplay(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $tester->run(['command' => 'foo3:bar'], ['decorated' => true, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception3decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=32'); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception4.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); + } + + public function testRenderExceptionWithDoubleWidthCharacters() + { + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=120'); + $application->register('foo')->setCode(function () { + throw new \Exception('エラーメッセージ'); + }); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $tester->run(['command' => 'foo'], ['decorated' => true, 'capture_stderr_separately' => true]); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth1decorated.txt', $tester->getErrorOutput(true), '->renderException() renders a pretty exceptions with previous exceptions'); + + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=32'); + $application->register('foo')->setCode(function () { + throw new \Exception('コマンドの実行中にエラーが発生しました。'); + }); + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo'], ['decorated' => false, 'capture_stderr_separately' => true]); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_doublewidth2.txt', $tester->getErrorOutput(true), '->renderException() wraps messages when they are bigger than the terminal'); + putenv('COLUMNS=120'); + } + + public function testRenderExceptionEscapesLines() + { + $application = new Application(); + $application->setAutoExit(false); + putenv('COLUMNS=22'); + $application->register('foo')->setCode(function () { + throw new \Exception('dont break here !'); + }); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo'], ['decorated' => false]); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); + putenv('COLUMNS=120'); + } + + public function testRenderExceptionLineBreaks() + { + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['getTerminalWidth'])->getMock(); + $application->setAutoExit(false); + $application->expects($this->any()) + ->method('getTerminalWidth') + ->willReturn(120); + $application->register('foo')->setCode(function () { + throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n"); + }); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo'], ['decorated' => false]); + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks'); + } + + public function testRenderExceptionStackTraceContainsRootException() + { + $application = new Application(); + $application->setAutoExit(false); + $application->register('foo')->setCode(function () { + throw new \Exception('Verbose exception'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo'], ['decorated' => false, 'verbosity' => Output::VERBOSITY_VERBOSE]); + + $this->assertStringContainsString(sprintf('() at %s:', __FILE__), $tester->getDisplay()); + } + + public function testRun() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->add($command = new \Foo1Command()); + $_SERVER['argv'] = ['cli.php', 'foo:bar1']; + + ob_start(); + $application->run(); + ob_end_clean(); + + $this->assertInstanceOf('Symfony\Component\Console\Input\ArgvInput', $command->input, '->run() creates an ArgvInput by default if none is given'); + $this->assertInstanceOf('Symfony\Component\Console\Output\ConsoleOutput', $command->output, '->run() creates a ConsoleOutput by default if none is given'); + + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $this->ensureStaticCommandHelp($application); + $tester = new ApplicationTester($application); + + $tester->run([], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run1.txt', $tester->getDisplay(true), '->run() runs the list command if no argument is passed'); + + $tester->run(['--help' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if --help is passed'); + + $tester->run(['-h' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run2.txt', $tester->getDisplay(true), '->run() runs the help command if -h is passed'); + + $tester->run(['command' => 'list', '--help' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if --help is passed'); + + $tester->run(['command' => 'list', '-h' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run3.txt', $tester->getDisplay(true), '->run() displays the help if -h is passed'); + + $tester->run(['--ansi' => true]); + $this->assertTrue($tester->getOutput()->isDecorated(), '->run() forces color output if --ansi is passed'); + + $tester->run(['--no-ansi' => true]); + $this->assertFalse($tester->getOutput()->isDecorated(), '->run() forces color output to be disabled if --no-ansi is passed'); + + $tester->run(['--version' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if --version is passed'); + + $tester->run(['-V' => true], ['decorated' => false]); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_run4.txt', $tester->getDisplay(true), '->run() displays the program version if -v is passed'); + + $tester->run(['command' => 'list', '--quiet' => true]); + $this->assertSame('', $tester->getDisplay(), '->run() removes all output if --quiet is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if --quiet is passed'); + + $tester->run(['command' => 'list', '-q' => true]); + $this->assertSame('', $tester->getDisplay(), '->run() removes all output if -q is passed'); + $this->assertFalse($tester->getInput()->isInteractive(), '->run() sets off the interactive mode if -q is passed'); + + $tester->run(['command' => 'list', '--verbose' => true]); + $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose is passed'); + + $tester->run(['command' => 'list', '--verbose' => 1]); + $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if --verbose=1 is passed'); + + $tester->run(['command' => 'list', '--verbose' => 2]); + $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to very verbose if --verbose=2 is passed'); + + $tester->run(['command' => 'list', '--verbose' => 3]); + $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to debug if --verbose=3 is passed'); + + $tester->run(['command' => 'list', '--verbose' => 4]); + $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if unknown --verbose level is passed'); + + $tester->run(['command' => 'list', '-v' => true]); + $this->assertSame(Output::VERBOSITY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); + + $tester->run(['command' => 'list', '-vv' => true]); + $this->assertSame(Output::VERBOSITY_VERY_VERBOSE, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); + + $tester->run(['command' => 'list', '-vvv' => true]); + $this->assertSame(Output::VERBOSITY_DEBUG, $tester->getOutput()->getVerbosity(), '->run() sets the output to verbose if -v is passed'); + + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->add(new \FooCommand()); + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'foo:bar', '--no-interaction' => true], ['decorated' => false]); + $this->assertSame('called'.\PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if --no-interaction is passed'); + + $tester->run(['command' => 'foo:bar', '-n' => true], ['decorated' => false]); + $this->assertSame('called'.\PHP_EOL, $tester->getDisplay(), '->run() does not call interact() if -n is passed'); + } + + public function testRunWithGlobalOptionAndNoCommand() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->getDefinition()->addOption(new InputOption('foo', 'f', InputOption::VALUE_OPTIONAL)); + + $output = new StreamOutput(fopen('php://memory', 'w', false)); + $input = new ArgvInput(['cli.php', '--foo', 'bar']); + + $this->assertSame(0, $application->run($input, $output)); + } + + /** + * Issue #9285. + * + * If the "verbose" option is just before an argument in ArgvInput, + * an argument value should not be treated as verbosity value. + * This test will fail with "Not enough arguments." if broken + */ + public function testVerboseValueNotBreakArguments() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->add(new \FooCommand()); + + $output = new StreamOutput(fopen('php://memory', 'w', false)); + + $input = new ArgvInput(['cli.php', '-v', 'foo:bar']); + $application->run($input, $output); + + $this->addToAssertionCount(1); + + $input = new ArgvInput(['cli.php', '--verbose', 'foo:bar']); + $application->run($input, $output); + + $this->addToAssertionCount(1); + } + + public function testRunReturnsIntegerExitCode() + { + $exception = new \Exception('', 4); + + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['doRun'])->getMock(); + $application->setAutoExit(false); + $application->expects($this->once()) + ->method('doRun') + ->willThrowException($exception); + + $exitCode = $application->run(new ArrayInput([]), new NullOutput()); + + $this->assertSame(4, $exitCode, '->run() returns integer exit code extracted from raised exception'); + } + + public function testRunDispatchesIntegerExitCode() + { + $passedRightValue = false; + + // We can assume here that some other test asserts that the event is dispatched at all + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) { + $passedRightValue = (4 === $event->getExitCode()); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \Exception('', 4); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'test']); + + $this->assertTrue($passedRightValue, '-> exit code 4 was passed in the console.terminate event'); + } + + public function testRunReturnsExitCodeOneForExceptionCodeZero() + { + $exception = new \Exception('', 0); + + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(['doRun'])->getMock(); + $application->setAutoExit(false); + $application->expects($this->once()) + ->method('doRun') + ->willThrowException($exception); + + $exitCode = $application->run(new ArrayInput([]), new NullOutput()); + + $this->assertSame(1, $exitCode, '->run() returns exit code 1 when exception code is 0'); + } + + public function testRunDispatchesExitCodeOneForExceptionCodeZero() + { + $passedRightValue = false; + + // We can assume here that some other test asserts that the event is dispatched at all + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use (&$passedRightValue) { + $passedRightValue = (1 === $event->getExitCode()); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('test')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \Exception(); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'test']); + + $this->assertTrue($passedRightValue, '-> exit code 1 was passed in the console.terminate event'); + } + + public function testAddingOptionWithDuplicateShortcut() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('An option with shortcut "e" already exists.'); + $dispatcher = new EventDispatcher(); + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->setDispatcher($dispatcher); + + $application->getDefinition()->addOption(new InputOption('--env', '-e', InputOption::VALUE_REQUIRED, 'Environment')); + + $application + ->register('foo') + ->setAliases(['f']) + ->setDefinition([new InputOption('survey', 'e', InputOption::VALUE_REQUIRED, 'My option with a shortcut.')]) + ->setCode(function (InputInterface $input, OutputInterface $output) {}) + ; + + $input = new ArrayInput(['command' => 'foo']); + $output = new NullOutput(); + + $application->run($input, $output); + } + + /** + * @dataProvider getAddingAlreadySetDefinitionElementData + */ + public function testAddingAlreadySetDefinitionElementData($def) + { + $this->expectException('LogicException'); + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application + ->register('foo') + ->setDefinition([$def]) + ->setCode(function (InputInterface $input, OutputInterface $output) {}) + ; + + $input = new ArrayInput(['command' => 'foo']); + $output = new NullOutput(); + $application->run($input, $output); + } + + public function getAddingAlreadySetDefinitionElementData() + { + return [ + [new InputArgument('command', InputArgument::REQUIRED)], + [new InputOption('quiet', '', InputOption::VALUE_NONE)], + [new InputOption('query', 'q', InputOption::VALUE_NONE)], + ]; + } + + public function testGetDefaultHelperSetReturnsDefaultValues() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $helperSet = $application->getHelperSet(); + + $this->assertTrue($helperSet->has('formatter')); + } + + public function testAddingSingleHelperSetOverwritesDefaultValues() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->setHelperSet(new HelperSet([new FormatterHelper()])); + + $helperSet = $application->getHelperSet(); + + $this->assertTrue($helperSet->has('formatter')); + + // no other default helper set should be returned + $this->assertFalse($helperSet->has('dialog')); + $this->assertFalse($helperSet->has('progress')); + } + + public function testOverwritingDefaultHelperSetOverwritesDefaultValues() + { + $application = new CustomApplication(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->setHelperSet(new HelperSet([new FormatterHelper()])); + + $helperSet = $application->getHelperSet(); + + $this->assertTrue($helperSet->has('formatter')); + + // no other default helper set should be returned + $this->assertFalse($helperSet->has('dialog')); + $this->assertFalse($helperSet->has('progress')); + } + + public function testGetDefaultInputDefinitionReturnsDefaultValues() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $inputDefinition = $application->getDefinition(); + + $this->assertTrue($inputDefinition->hasArgument('command')); + + $this->assertTrue($inputDefinition->hasOption('help')); + $this->assertTrue($inputDefinition->hasOption('quiet')); + $this->assertTrue($inputDefinition->hasOption('verbose')); + $this->assertTrue($inputDefinition->hasOption('version')); + $this->assertTrue($inputDefinition->hasOption('ansi')); + $this->assertTrue($inputDefinition->hasOption('no-ansi')); + $this->assertTrue($inputDefinition->hasOption('no-interaction')); + } + + public function testOverwritingDefaultInputDefinitionOverwritesDefaultValues() + { + $application = new CustomApplication(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $inputDefinition = $application->getDefinition(); + + // check whether the default arguments and options are not returned any more + $this->assertFalse($inputDefinition->hasArgument('command')); + + $this->assertFalse($inputDefinition->hasOption('help')); + $this->assertFalse($inputDefinition->hasOption('quiet')); + $this->assertFalse($inputDefinition->hasOption('verbose')); + $this->assertFalse($inputDefinition->hasOption('version')); + $this->assertFalse($inputDefinition->hasOption('ansi')); + $this->assertFalse($inputDefinition->hasOption('no-ansi')); + $this->assertFalse($inputDefinition->hasOption('no-interaction')); + + $this->assertTrue($inputDefinition->hasOption('custom')); + } + + public function testSettingCustomInputDefinitionOverwritesDefaultValues() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->setDefinition(new InputDefinition([new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')])); + + $inputDefinition = $application->getDefinition(); + + // check whether the default arguments and options are not returned any more + $this->assertFalse($inputDefinition->hasArgument('command')); + + $this->assertFalse($inputDefinition->hasOption('help')); + $this->assertFalse($inputDefinition->hasOption('quiet')); + $this->assertFalse($inputDefinition->hasOption('verbose')); + $this->assertFalse($inputDefinition->hasOption('version')); + $this->assertFalse($inputDefinition->hasOption('ansi')); + $this->assertFalse($inputDefinition->hasOption('no-ansi')); + $this->assertFalse($inputDefinition->hasOption('no-interaction')); + + $this->assertTrue($inputDefinition->hasOption('custom')); + } + + public function testRunWithDispatcher() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setDispatcher($this->getDispatcher()); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + $this->assertEquals('before.foo.after.'.\PHP_EOL, $tester->getDisplay()); + } + + public function testRunWithExceptionAndDispatcher() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('error'); + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \RuntimeException('foo'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + } + + public function testRunDispatchesAllEventsWithException() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + + throw new \RuntimeException('foo'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + $this->assertStringContainsString('before.foo.error.after.', $tester->getDisplay()); + } + + public function testRunDispatchesAllEventsWithExceptionInListener() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.command', function () { + throw new \RuntimeException('foo'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + $this->assertStringContainsString('before.error.after.', $tester->getDisplay()); + } + + /** + * @requires PHP 7 + */ + public function testRunWithError() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(['command' => 'dym']); + $this->fail('Error expected.'); + } catch (\Error $e) { + $this->assertSame('dymerr', $e->getMessage()); + } + } + + public function testRunAllowsErrorListenersToSilenceTheException() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $event->getOutput()->write('silenced.'); + + $event->setExitCode(0); + }); + + $dispatcher->addListener('console.command', function () { + throw new \RuntimeException('foo'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + $this->assertStringContainsString('before.error.silenced.after.', $tester->getDisplay()); + $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $tester->getStatusCode()); + } + + public function testConsoleErrorEventIsTriggeredOnCommandNotFound() + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $this->assertNull($event->getCommand()); + $this->assertInstanceOf(CommandNotFoundException::class, $event->getError()); + $event->getOutput()->write('silenced command not found'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'unknown']); + $this->assertStringContainsString('silenced command not found', $tester->getDisplay()); + $this->assertEquals(1, $tester->getStatusCode()); + } + + /** + * @group legacy + * @expectedDeprecation The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead. + */ + public function testLegacyExceptionListenersAreStillTriggered() + { + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { + $event->getOutput()->write('caught.'); + + $event->setException(new \RuntimeException('replaced in caught.')); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + throw new \RuntimeException('foo'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo']); + $this->assertStringContainsString('before.caught.error.after.', $tester->getDisplay()); + $this->assertStringContainsString('replaced in caught.', $tester->getDisplay()); + } + + /** + * @requires PHP 7 + */ + public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + $application->setDispatcher(new EventDispatcher()); + + $application->register('dym')->setCode(function () { + throw new \Error('Something went wrong.'); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(['command' => 'dym']); + $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); + } catch (\Error $e) { + $this->assertSame('Something went wrong.', $e->getMessage()); + } + } + + /** + * @requires PHP 7 + */ + public function testRunWithErrorAndDispatcher() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('error'); + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + $application->setCatchExceptions(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'dym']); + $this->assertStringContainsString('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + /** + * @requires PHP 7 + */ + public function testRunDispatchesAllEventsWithError() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dym')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dym.'); + + throw new \Error('dymerr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'dym']); + $this->assertStringContainsString('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); + } + + /** + * @requires PHP 7 + */ + public function testRunWithErrorFailingStatusCode() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher()); + $application->setAutoExit(false); + + $application->register('dus')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('dus.'); + + throw new \Error('duserr'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'dus']); + $this->assertSame(1, $tester->getStatusCode(), 'Status code should be 1'); + } + + public function testRunWithDispatcherSkippingCommand() + { + $application = new Application(); + $application->setDispatcher($this->getDispatcher(true)); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $exitCode = $tester->run(['command' => 'foo']); + $this->assertStringContainsString('before.after.', $tester->getDisplay()); + $this->assertEquals(ConsoleCommandEvent::RETURN_CODE_DISABLED, $exitCode); + } + + public function testRunWithDispatcherAccessingInputOptions() + { + $noInteractionValue = null; + $quietValue = null; + + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$noInteractionValue, &$quietValue) { + $input = $event->getInput(); + + $noInteractionValue = $input->getOption('no-interaction'); + $quietValue = $input->getOption('quiet'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo', '--no-interaction' => true]); + + $this->assertTrue($noInteractionValue); + $this->assertFalse($quietValue); + } + + public function testRunWithDispatcherAddingInputOptions() + { + $extraValue = null; + + $dispatcher = $this->getDispatcher(); + $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use (&$extraValue) { + $definition = $event->getCommand()->getDefinition(); + $input = $event->getInput(); + + $definition->addOption(new InputOption('extra', null, InputOption::VALUE_REQUIRED)); + $input->bind($definition); + + $extraValue = $input->getOption('extra'); + }); + + $application = new Application(); + $application->setDispatcher($dispatcher); + $application->setAutoExit(false); + + $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { + $output->write('foo.'); + }); + + $tester = new ApplicationTester($application); + $tester->run(['command' => 'foo', '--extra' => 'some test value']); + + $this->assertEquals('some test value', $extraValue); + } + + /** + * @group legacy + */ + public function testTerminalDimensions() + { + $application = new Application(); + $originalDimensions = $application->getTerminalDimensions(); + $this->assertCount(2, $originalDimensions); + + $width = 80; + if ($originalDimensions[0] == $width) { + $width = 100; + } + + $application->setTerminalDimensions($width, 80); + $this->assertSame([$width, 80], $application->getTerminalDimensions()); + } + + public function testSetRunCustomDefaultCommand() + { + $command = new \FooCommand(); + + $application = new Application(); + $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName()); + + $tester = new ApplicationTester($application); + $tester->run([], ['interactive' => false]); + $this->assertEquals('called'.\PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + + $application = new CustomDefaultCommandApplication(); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run([], ['interactive' => false]); + + $this->assertEquals('called'.\PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + } + + public function testSetRunCustomDefaultCommandWithOption() + { + $command = new \FooOptCommand(); + + $application = new Application(); + $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName()); + + $tester = new ApplicationTester($application); + $tester->run(['--fooopt' => 'opt'], ['interactive' => false]); + + $this->assertEquals('called'.\PHP_EOL.'opt'.\PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + } + + public function testSetRunCustomSingleCommand() + { + $command = new \FooCommand(); + + $application = new Application(); + $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName(), true); + + $tester = new ApplicationTester($application); + + $tester->run([]); + $this->assertStringContainsString('called', $tester->getDisplay()); + + $tester->run(['--help' => true]); + $this->assertStringContainsString('The foo:bar command', $tester->getDisplay()); + } + + public function testRunLazyCommandService() + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new AddConsoleCommandPass()); + $container + ->register('lazy-command', LazyCommand::class) + ->addTag('console.command', ['command' => 'lazy:command']) + ->addTag('console.command', ['command' => 'lazy:alias']) + ->addTag('console.command', ['command' => 'lazy:alias2']); + $container->compile(); + + $application = new Application(); + $application->setCommandLoader($container->get('console.command_loader')); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + + $tester->run(['command' => 'lazy:command']); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(['command' => 'lazy:alias']); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(['command' => 'lazy:alias2']); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $command = $application->get('lazy:command'); + $this->assertSame(['lazy:alias', 'lazy:alias2'], $command->getAliases()); + } + + public function testGetDisabledLazyCommand() + { + $this->expectException('Symfony\Component\Console\Exception\CommandNotFoundException'); + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); + $application->get('disabled'); + } + + public function testHasReturnsFalseForDisabledLazyCommand() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); + $this->assertFalse($application->has('disabled')); + } + + public function testAllExcludesDisabledLazyCommand() + { + $application = new Application(); + $application->setCommandLoader(new FactoryCommandLoader(['disabled' => function () { return new DisabledCommand(); }])); + $this->assertArrayNotHasKey('disabled', $application->all()); + } + + public function testFindAlternativesDoesNotLoadSameNamespaceCommandsOnExactMatch() + { + $application = new Application(); + $application->setAutoExit(false); + + $loaded = []; + + $application->setCommandLoader(new FactoryCommandLoader([ + 'foo:bar' => function () use (&$loaded) { + $loaded['foo:bar'] = true; + + return (new Command('foo:bar'))->setCode(function () {}); + }, + 'foo' => function () use (&$loaded) { + $loaded['foo'] = true; + + return (new Command('foo'))->setCode(function () {}); + }, + ])); + + $application->run(new ArrayInput(['command' => 'foo']), new NullOutput()); + + $this->assertSame(['foo' => true], $loaded); + } + + protected function getDispatcher($skipCommand = false) + { + $dispatcher = new EventDispatcher(); + $dispatcher->addListener('console.command', function (ConsoleCommandEvent $event) use ($skipCommand) { + $event->getOutput()->write('before.'); + + if ($skipCommand) { + $event->disableCommand(); + } + }); + $dispatcher->addListener('console.terminate', function (ConsoleTerminateEvent $event) use ($skipCommand) { + $event->getOutput()->writeln('after.'); + + if (!$skipCommand) { + $event->setExitCode(ConsoleCommandEvent::RETURN_CODE_DISABLED); + } + }); + $dispatcher->addListener('console.error', function (ConsoleErrorEvent $event) { + $event->getOutput()->write('error.'); + + $event->setError(new \LogicException('error.', $event->getExitCode(), $event->getError())); + }); + + return $dispatcher; + } + + /** + * @requires PHP 7 + */ + public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled() + { + $application = new Application(); + $application->setAutoExit(false); + $application->setDispatcher(new EventDispatcher()); + + $application->register('dym')->setCode(function () { + throw new \Error('Something went wrong.'); + }); + + $tester = new ApplicationTester($application); + + try { + $tester->run(['command' => 'dym']); + $this->fail('->run() should rethrow PHP errors if not handled via ConsoleErrorEvent.'); + } catch (\Error $e) { + $this->assertSame('Something went wrong.', $e->getMessage()); + } + } + + public function testCommandNameMismatchWithCommandLoaderKeyThrows() + { + $this->expectException(CommandNotFoundException::class); + $this->expectExceptionMessage('The "test" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".'); + + $app = new Application(); + $loader = new FactoryCommandLoader([ + 'test' => static function () { return new Command('test-command'); }, + ]); + + $app->setCommandLoader($loader); + $app->get('test'); + } +} + +class CustomApplication extends Application +{ + /** + * Overwrites the default input definition. + * + * @return InputDefinition An InputDefinition instance + */ + protected function getDefaultInputDefinition() + { + return new InputDefinition([new InputOption('--custom', '-c', InputOption::VALUE_NONE, 'Set the custom input definition.')]); + } + + /** + * Gets the default helper set with the helpers that should always be available. + * + * @return HelperSet A HelperSet instance + */ + protected function getDefaultHelperSet() + { + return new HelperSet([new FormatterHelper()]); + } +} + +class CustomDefaultCommandApplication extends Application +{ + /** + * Overwrites the constructor in order to set a different default command. + */ + public function __construct() + { + parent::__construct(); + + $command = new \FooCommand(); + $this->add($command); + $this->setDefaultCommand($command->getName()); + } +} + +class LazyCommand extends Command +{ + public function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('lazy-command called'); + } +} + +class DisabledCommand extends Command +{ + public function isEnabled() + { + return false; + } +} diff --git a/www/multitube/vendor/symfony/console/Tests/Command/CommandTest.php b/www/multitube/vendor/symfony/console/Tests/Command/CommandTest.php new file mode 100644 index 0000000..7421c09 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tests/Command/CommandTest.php @@ -0,0 +1,430 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\FormatterHelper; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputDefinition; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\StringInput; +use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Tester\CommandTester; + +class CommandTest extends TestCase +{ + protected static $fixturesPath; + + public static function setUpBeforeClass() + { + self::$fixturesPath = __DIR__.'/../Fixtures/'; + require_once self::$fixturesPath.'/TestCommand.php'; + } + + public function testConstructor() + { + $command = new Command('foo:bar'); + $this->assertEquals('foo:bar', $command->getName(), '__construct() takes the command name as its first argument'); + } + + public function testCommandNameCannotBeEmpty() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('The command defined in "Symfony\Component\Console\Command\Command" cannot have an empty name.'); + (new Application())->add(new Command()); + } + + public function testSetApplication() + { + $application = new Application(); + $command = new \TestCommand(); + $command->setApplication($application); + $this->assertEquals($application, $command->getApplication(), '->setApplication() sets the current application'); + $this->assertEquals($application->getHelperSet(), $command->getHelperSet()); + } + + public function testSetApplicationNull() + { + $command = new \TestCommand(); + $command->setApplication(null); + $this->assertNull($command->getHelperSet()); + } + + public function testSetGetDefinition() + { + $command = new \TestCommand(); + $ret = $command->setDefinition($definition = new InputDefinition()); + $this->assertEquals($command, $ret, '->setDefinition() implements a fluent interface'); + $this->assertEquals($definition, $command->getDefinition(), '->setDefinition() sets the current InputDefinition instance'); + $command->setDefinition([new InputArgument('foo'), new InputOption('bar')]); + $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); + $this->assertTrue($command->getDefinition()->hasOption('bar'), '->setDefinition() also takes an array of InputArguments and InputOptions as an argument'); + $command->setDefinition(new InputDefinition()); + } + + public function testAddArgument() + { + $command = new \TestCommand(); + $ret = $command->addArgument('foo'); + $this->assertEquals($command, $ret, '->addArgument() implements a fluent interface'); + $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->addArgument() adds an argument to the command'); + } + + public function testAddOption() + { + $command = new \TestCommand(); + $ret = $command->addOption('foo'); + $this->assertEquals($command, $ret, '->addOption() implements a fluent interface'); + $this->assertTrue($command->getDefinition()->hasOption('foo'), '->addOption() adds an option to the command'); + } + + public function testSetHidden() + { + $command = new \TestCommand(); + $command->setHidden(true); + $this->assertTrue($command->isHidden()); + } + + public function testGetNamespaceGetNameSetName() + { + $command = new \TestCommand(); + $this->assertEquals('namespace:name', $command->getName(), '->getName() returns the command name'); + $command->setName('foo'); + $this->assertEquals('foo', $command->getName(), '->setName() sets the command name'); + + $ret = $command->setName('foobar:bar'); + $this->assertEquals($command, $ret, '->setName() implements a fluent interface'); + $this->assertEquals('foobar:bar', $command->getName(), '->setName() sets the command name'); + } + + /** + * @dataProvider provideInvalidCommandNames + */ + public function testInvalidCommandNames($name) + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage(sprintf('Command name "%s" is invalid.', $name)); + + $command = new \TestCommand(); + $command->setName($name); + } + + public function provideInvalidCommandNames() + { + return [ + [''], + ['foo:'], + ]; + } + + public function testGetSetDescription() + { + $command = new \TestCommand(); + $this->assertEquals('description', $command->getDescription(), '->getDescription() returns the description'); + $ret = $command->setDescription('description1'); + $this->assertEquals($command, $ret, '->setDescription() implements a fluent interface'); + $this->assertEquals('description1', $command->getDescription(), '->setDescription() sets the description'); + } + + public function testGetSetHelp() + { + $command = new \TestCommand(); + $this->assertEquals('help', $command->getHelp(), '->getHelp() returns the help'); + $ret = $command->setHelp('help1'); + $this->assertEquals($command, $ret, '->setHelp() implements a fluent interface'); + $this->assertEquals('help1', $command->getHelp(), '->setHelp() sets the help'); + $command->setHelp(''); + $this->assertEquals('', $command->getHelp(), '->getHelp() does not fall back to the description'); + } + + public function testGetProcessedHelp() + { + $command = new \TestCommand(); + $command->setHelp('The %command.name% command does... Example: php %command.full_name%.'); + $this->assertStringContainsString('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly'); + $this->assertStringNotContainsString('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name%'); + + $command = new \TestCommand(); + $command->setHelp(''); + $this->assertStringContainsString('description', $command->getProcessedHelp(), '->getProcessedHelp() falls back to the description'); + + $command = new \TestCommand(); + $command->setHelp('The %command.name% command does... Example: php %command.full_name%.'); + $application = new Application(); + $application->add($command); + $application->setDefaultCommand('namespace:name', true); + $this->assertStringContainsString('The namespace:name command does...', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.name% correctly in single command applications'); + $this->assertStringNotContainsString('%command.full_name%', $command->getProcessedHelp(), '->getProcessedHelp() replaces %command.full_name% in single command applications'); + } + + public function testGetSetAliases() + { + $command = new \TestCommand(); + $this->assertEquals(['name'], $command->getAliases(), '->getAliases() returns the aliases'); + $ret = $command->setAliases(['name1']); + $this->assertEquals($command, $ret, '->setAliases() implements a fluent interface'); + $this->assertEquals(['name1'], $command->getAliases(), '->setAliases() sets the aliases'); + } + + public function testSetAliasesNull() + { + $command = new \TestCommand(); + $this->expectException('InvalidArgumentException'); + $command->setAliases(null); + } + + public function testGetSynopsis() + { + $command = new \TestCommand(); + $command->addOption('foo'); + $command->addArgument('bar'); + $this->assertEquals('namespace:name [--foo] [--] []', $command->getSynopsis(), '->getSynopsis() returns the synopsis'); + } + + public function testAddGetUsages() + { + $command = new \TestCommand(); + $command->addUsage('foo1'); + $command->addUsage('foo2'); + $this->assertContains('namespace:name foo1', $command->getUsages()); + $this->assertContains('namespace:name foo2', $command->getUsages()); + } + + public function testGetHelper() + { + $application = new Application(); + $command = new \TestCommand(); + $command->setApplication($application); + $formatterHelper = new FormatterHelper(); + $this->assertEquals($formatterHelper->getName(), $command->getHelper('formatter')->getName(), '->getHelper() returns the correct helper'); + } + + public function testGetHelperWithoutHelperSet() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('Cannot retrieve helper "formatter" because there is no HelperSet defined.'); + $command = new \TestCommand(); + $command->getHelper('formatter'); + } + + public function testMergeApplicationDefinition() + { + $application1 = new Application(); + $application1->getDefinition()->addArguments([new InputArgument('foo')]); + $application1->getDefinition()->addOptions([new InputOption('bar')]); + $command = new \TestCommand(); + $command->setApplication($application1); + $command->setDefinition($definition = new InputDefinition([new InputArgument('bar'), new InputOption('foo')])); + + $r = new \ReflectionObject($command); + $m = $r->getMethod('mergeApplicationDefinition'); + $m->setAccessible(true); + $m->invoke($command); + $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); + $this->assertTrue($command->getDefinition()->hasArgument('bar'), '->mergeApplicationDefinition() merges the application arguments and the command arguments'); + $this->assertTrue($command->getDefinition()->hasOption('foo'), '->mergeApplicationDefinition() merges the application options and the command options'); + $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition() merges the application options and the command options'); + + $m->invoke($command); + $this->assertEquals(3, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments and options'); + } + + public function testMergeApplicationDefinitionWithoutArgsThenWithArgsAddsArgs() + { + $application1 = new Application(); + $application1->getDefinition()->addArguments([new InputArgument('foo')]); + $application1->getDefinition()->addOptions([new InputOption('bar')]); + $command = new \TestCommand(); + $command->setApplication($application1); + $command->setDefinition($definition = new InputDefinition([])); + + $r = new \ReflectionObject($command); + $m = $r->getMethod('mergeApplicationDefinition'); + $m->setAccessible(true); + $m->invoke($command, false); + $this->assertTrue($command->getDefinition()->hasOption('bar'), '->mergeApplicationDefinition(false) merges the application and the command options'); + $this->assertFalse($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(false) does not merge the application arguments'); + + $m->invoke($command, true); + $this->assertTrue($command->getDefinition()->hasArgument('foo'), '->mergeApplicationDefinition(true) merges the application arguments and the command arguments'); + + $m->invoke($command); + $this->assertEquals(2, $command->getDefinition()->getArgumentCount(), '->mergeApplicationDefinition() does not try to merge twice the application arguments'); + } + + public function testRunInteractive() + { + $tester = new CommandTester(new \TestCommand()); + + $tester->execute([], ['interactive' => true]); + + $this->assertEquals('interact called'.\PHP_EOL.'execute called'.\PHP_EOL, $tester->getDisplay(), '->run() calls the interact() method if the input is interactive'); + } + + public function testRunNonInteractive() + { + $tester = new CommandTester(new \TestCommand()); + + $tester->execute([], ['interactive' => false]); + + $this->assertEquals('execute called'.\PHP_EOL, $tester->getDisplay(), '->run() does not call the interact() method if the input is not interactive'); + } + + public function testExecuteMethodNeedsToBeOverridden() + { + $this->expectException('LogicException'); + $this->expectExceptionMessage('You must override the execute() method in the concrete command class.'); + $command = new Command('foo'); + $command->run(new StringInput(''), new NullOutput()); + } + + public function testRunWithInvalidOption() + { + $this->expectException('Symfony\Component\Console\Exception\InvalidOptionException'); + $this->expectExceptionMessage('The "--bar" option does not exist.'); + $command = new \TestCommand(); + $tester = new CommandTester($command); + $tester->execute(['--bar' => true]); + } + + public function testRunReturnsIntegerExitCode() + { + $command = new \TestCommand(); + $exitCode = $command->run(new StringInput(''), new NullOutput()); + $this->assertSame(0, $exitCode, '->run() returns integer exit code (treats null as 0)'); + + $command = $this->getMockBuilder('TestCommand')->setMethods(['execute'])->getMock(); + $command->expects($this->once()) + ->method('execute') + ->willReturn('2.3'); + $exitCode = $command->run(new StringInput(''), new NullOutput()); + $this->assertSame(2, $exitCode, '->run() returns integer exit code (casts numeric to int)'); + } + + public function testRunWithApplication() + { + $command = new \TestCommand(); + $command->setApplication(new Application()); + $exitCode = $command->run(new StringInput(''), new NullOutput()); + + $this->assertSame(0, $exitCode, '->run() returns an integer exit code'); + } + + public function testRunReturnsAlwaysInteger() + { + $command = new \TestCommand(); + + $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); + } + + public function testRunWithProcessTitle() + { + $command = new \TestCommand(); + $command->setApplication(new Application()); + $command->setProcessTitle('foo'); + $this->assertSame(0, $command->run(new StringInput(''), new NullOutput())); + if (\function_exists('cli_set_process_title')) { + if (null === @cli_get_process_title() && 'Darwin' === \PHP_OS) { + $this->markTestSkipped('Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.'); + } + $this->assertEquals('foo', cli_get_process_title()); + } + } + + public function testSetCode() + { + $command = new \TestCommand(); + $ret = $command->setCode(function (InputInterface $input, OutputInterface $output) { + $output->writeln('from the code...'); + }); + $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); + $tester = new CommandTester($command); + $tester->execute([]); + $this->assertEquals('interact called'.\PHP_EOL.'from the code...'.\PHP_EOL, $tester->getDisplay()); + } + + public function getSetCodeBindToClosureTests() + { + return [ + [true, 'not bound to the command'], + [false, 'bound to the command'], + ]; + } + + /** + * @dataProvider getSetCodeBindToClosureTests + */ + public function testSetCodeBindToClosure($previouslyBound, $expected) + { + $code = createClosure(); + if ($previouslyBound) { + $code = $code->bindTo($this); + } + + $command = new \TestCommand(); + $command->setCode($code); + $tester = new CommandTester($command); + $tester->execute([]); + $this->assertEquals('interact called'.\PHP_EOL.$expected.\PHP_EOL, $tester->getDisplay()); + } + + public function testSetCodeWithStaticClosure() + { + $command = new \TestCommand(); + $command->setCode(self::createClosure()); + $tester = new CommandTester($command); + $tester->execute([]); + + if (\PHP_VERSION_ID < 70000) { + // Cannot bind static closures in PHP 5 + $this->assertEquals('interact called'.\PHP_EOL.'not bound'.\PHP_EOL, $tester->getDisplay()); + } else { + // Can bind static closures in PHP 7 + $this->assertEquals('interact called'.\PHP_EOL.'bound'.\PHP_EOL, $tester->getDisplay()); + } + } + + private static function createClosure() + { + return function (InputInterface $input, OutputInterface $output) { + $output->writeln(isset($this) ? 'bound' : 'not bound'); + }; + } + + public function testSetCodeWithNonClosureCallable() + { + $command = new \TestCommand(); + $ret = $command->setCode([$this, 'callableMethodCommand']); + $this->assertEquals($command, $ret, '->setCode() implements a fluent interface'); + $tester = new CommandTester($command); + $tester->execute([]); + $this->assertEquals('interact called'.\PHP_EOL.'from the code...'.\PHP_EOL, $tester->getDisplay()); + } + + public function callableMethodCommand(InputInterface $input, OutputInterface $output) + { + $output->writeln('from the code...'); + } +} + +// In order to get an unbound closure, we should create it outside a class +// scope. +function createClosure() +{ + return function (InputInterface $input, OutputInterface $output) { + $output->writeln($this instanceof Command ? 'bound to the command' : 'not bound to the command'); + }; +} diff --git a/www/multitube/vendor/symfony/console/Tests/Command/HelpCommandTest.php b/www/multitube/vendor/symfony/console/Tests/Command/HelpCommandTest.php new file mode 100644 index 0000000..5b25550 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tests/Command/HelpCommandTest.php @@ -0,0 +1,71 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\HelpCommand; +use Symfony\Component\Console\Command\ListCommand; +use Symfony\Component\Console\Tester\CommandTester; + +class HelpCommandTest extends TestCase +{ + public function testExecuteForCommandAlias() + { + $command = new HelpCommand(); + $command->setApplication(new Application()); + $commandTester = new CommandTester($command); + $commandTester->execute(['command_name' => 'li'], ['decorated' => false]); + $this->assertStringContainsString('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); + $this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); + $this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command alias'); + } + + public function testExecuteForCommand() + { + $command = new HelpCommand(); + $commandTester = new CommandTester($command); + $command->setCommand(new ListCommand()); + $commandTester->execute([], ['decorated' => false]); + $this->assertStringContainsString('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + } + + public function testExecuteForCommandWithXmlOption() + { + $command = new HelpCommand(); + $commandTester = new CommandTester($command); + $command->setCommand(new ListCommand()); + $commandTester->execute(['--format' => 'xml']); + $this->assertStringContainsString('getDisplay(), '->execute() returns an XML help text if --xml is passed'); + } + + public function testExecuteForApplicationCommand() + { + $application = new Application(); + $commandTester = new CommandTester($application->get('help')); + $commandTester->execute(['command_name' => 'list']); + $this->assertStringContainsString('list [options] [--] []', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertStringContainsString('format=FORMAT', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertStringContainsString('raw', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + } + + public function testExecuteForApplicationCommandWithXmlOption() + { + $application = new Application(); + $commandTester = new CommandTester($application->get('help')); + $commandTester->execute(['command_name' => 'list', '--format' => 'xml']); + $this->assertStringContainsString('list [--raw] [--format FORMAT] [--] [<namespace>]', $commandTester->getDisplay(), '->execute() returns a text help for the given command'); + $this->assertStringContainsString('getDisplay(), '->execute() returns an XML help text if --format=xml is passed'); + } +} diff --git a/www/multitube/vendor/symfony/console/Tests/Command/ListCommandTest.php b/www/multitube/vendor/symfony/console/Tests/Command/ListCommandTest.php new file mode 100644 index 0000000..3908ca5 --- /dev/null +++ b/www/multitube/vendor/symfony/console/Tests/Command/ListCommandTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; + +class ListCommandTest extends TestCase +{ + public function testExecuteListsCommands() + { + $application = new Application(); + $commandTester = new CommandTester($command = $application->get('list')); + $commandTester->execute(['command' => $command->getName()], ['decorated' => false]); + + $this->assertMatchesRegularExpression('/help\s{2,}Displays help for a command/', $commandTester->getDisplay(), '->execute() returns a list of available commands'); + } + + public function testExecuteListsCommandsWithXmlOption() + { + $application = new Application(); + $commandTester = new CommandTester($command = $application->get('list')); + $commandTester->execute(['command' => $command->getName(), '--format' => 'xml']); + $this->assertMatchesRegularExpression('/%s', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : ''); + } + + /** + * Formats an array as a string. + */ + private function formatArgs(array $args): string + { + $result = []; + foreach ($args as $key => $item) { + if ('object' === $item[0]) { + $formattedValue = sprintf('object(%s)', $this->formatClass($item[1])); + } elseif ('array' === $item[0]) { + $formattedValue = sprintf('array(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + } elseif ('null' === $item[0]) { + $formattedValue = 'null'; + } elseif ('boolean' === $item[0]) { + $formattedValue = ''.strtolower(var_export($item[1], true)).''; + } elseif ('resource' === $item[0]) { + $formattedValue = 'resource'; + } else { + $formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true))); + } + + $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); + } + + return implode(', ', $result); + } + + /** + * HTML-encodes a string. + */ + private function escapeHtml(string $str): string + { + return htmlspecialchars($str, \ENT_COMPAT | \ENT_SUBSTITUTE, $this->charset); + } + + private function getSymfonyGhostAsSvg(): string + { + return ''.$this->addElementToGhost().''; + } + + private function addElementToGhost(): string + { + if (!isset(self::GHOST_ADDONS[date('m-d')])) { + return ''; + } + + return ''; + } +} diff --git a/www/multitube/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/www/multitube/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php new file mode 100644 index 0000000..64d7551 --- /dev/null +++ b/www/multitube/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Composer\Autoload\ClassLoader as ComposerClassLoader; +use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader; +use Symfony\Component\Debug\DebugClassLoader; +use Symfony\Component\Debug\Exception\ClassNotFoundException; +use Symfony\Component\Debug\Exception\FatalErrorException; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ClassNotFoundFatalErrorHandler::class, \Symfony\Component\ErrorHandler\FatalErrorHandler\ClassNotFoundFatalErrorHandler::class), \E_USER_DEPRECATED); + +/** + * ErrorHandler for classes that do not exist. + * + * @author Fabien Potencier + * + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\FatalErrorHandler\ClassNotFoundFatalErrorHandler instead. + */ +class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + if (!preg_match('/^(Class|Interface|Trait) [\'"]([^\'"]+)[\'"] not found$/', $error['message'], $matches)) { + return null; + } + $typeName = strtolower($matches[1]); + $fullyQualifiedClassName = $matches[2]; + + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) { + $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix); + $tail = ' for another namespace?'; + } else { + $className = $fullyQualifiedClassName; + $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className); + $tail = '?'; + } + + if ($candidates = $this->getClassCandidates($className)) { + $tail = array_pop($candidates).'"?'; + if ($candidates) { + $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail; + } else { + $tail = ' for "'.$tail; + } + } + $message .= "\nDid you forget a \"use\" statement".$tail; + + return new ClassNotFoundException($message, $exception); + } + + /** + * Tries to guess the full namespace for a given class name. + * + * By default, it looks for PSR-0 and PSR-4 classes registered via a Symfony or a Composer + * autoloader (that should cover all common cases). + * + * @param string $class A class name (without its namespace) + * + * @return array An array of possible fully qualified class names + */ + private function getClassCandidates(string $class): array + { + if (!\is_array($functions = spl_autoload_functions())) { + return []; + } + + // find Symfony and Composer autoloaders + $classes = []; + + foreach ($functions as $function) { + if (!\is_array($function)) { + continue; + } + // get class loaders wrapped by DebugClassLoader + if ($function[0] instanceof DebugClassLoader) { + $function = $function[0]->getClassLoader(); + + if (!\is_array($function)) { + continue; + } + } + + if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader) { + foreach ($function[0]->getPrefixes() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + } + if ($function[0] instanceof ComposerClassLoader) { + foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) { + foreach ($paths as $path) { + $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix)); + } + } + } + } + + return array_unique($classes); + } + + private function findClassInPath(string $path, string $class, string $prefix): array + { + if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { + return []; + } + + $classes = []; + $filename = $class.'.php'; + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { + $classes[] = $class; + } + } + + return $classes; + } + + private function convertFileToClass(string $path, string $file, string $prefix): ?string + { + $candidates = [ + // namespaced class + $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), + // namespaced class (with target dir) + $prefix.$namespacedClass, + // namespaced class (with target dir and separator) + $prefix.'\\'.$namespacedClass, + // PEAR class + str_replace('\\', '_', $namespacedClass), + // PEAR class (with target dir) + str_replace('\\', '_', $prefix.$namespacedClass), + // PEAR class (with target dir and separator) + str_replace('\\', '_', $prefix.'\\'.$namespacedClass), + ]; + + if ($prefix) { + $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); + } + + // We cannot use the autoloader here as most of them use require; but if the class + // is not found, the new autoloader call will require the file again leading to a + // "cannot redeclare class" error. + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + + try { + require_once $file; + } catch (\Throwable $e) { + return null; + } + + foreach ($candidates as $candidate) { + if ($this->classExists($candidate)) { + return $candidate; + } + } + + return null; + } + + private function classExists(string $class): bool + { + return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + } +} diff --git a/www/multitube/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php b/www/multitube/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php new file mode 100644 index 0000000..cc7a0ff --- /dev/null +++ b/www/multitube/vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\FatalErrorException; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalErrorHandlerInterface::class, \Symfony\Component\ErrorHandler\FatalErrorHandler\FatalErrorHandlerInterface::class), \E_USER_DEPRECATED); + +/** + * Attempts to convert fatal errors to exceptions. + * + * @author Fabien Potencier + * + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\FatalErrorHandler\FatalErrorHandlerInterface instead. + */ +interface FatalErrorHandlerInterface +{ + /** + * Attempts to convert an error into an exception. + * + * @param array $error An array as returned by error_get_last() + * + * @return FatalErrorException|null A FatalErrorException instance if the class is able to convert the error, null otherwise + */ + public function handleError(array $error, FatalErrorException $exception); +} diff --git a/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php new file mode 100644 index 0000000..95096a9 --- /dev/null +++ b/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\Exception\UndefinedFunctionException; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionFatalErrorHandler::class, \Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer::class), \E_USER_DEPRECATED); + +/** + * ErrorHandler for undefined functions. + * + * @author Fabien Potencier + * + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedFunctionErrorEnhancer instead. + */ +class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + $messageLen = \strlen($error['message']); + $notFoundSuffix = '()'; + $notFoundSuffixLen = \strlen($notFoundSuffix); + if ($notFoundSuffixLen > $messageLen) { + return null; + } + + if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { + return null; + } + + $prefix = 'Call to undefined function '; + $prefixLen = \strlen($prefix); + if (0 !== strpos($error['message'], $prefix)) { + return null; + } + + $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); + if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) { + $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1); + $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex); + $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix); + } else { + $functionName = $fullyQualifiedFunctionName; + $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); + } + + $candidates = []; + foreach (get_defined_functions() as $type => $definedFunctionNames) { + foreach ($definedFunctionNames as $definedFunctionName) { + if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { + $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1); + } else { + $definedFunctionNameBasename = $definedFunctionName; + } + + if ($definedFunctionNameBasename === $functionName) { + $candidates[] = '\\'.$definedFunctionName; + } + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedFunctionException($message, $exception); + } +} diff --git a/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php new file mode 100644 index 0000000..4f622de --- /dev/null +++ b/www/multitube/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Debug\FatalErrorHandler; + +use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\Exception\UndefinedMethodException; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodFatalErrorHandler::class, \Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer::class), \E_USER_DEPRECATED); + +/** + * ErrorHandler for undefined methods. + * + * @author Grégoire Pineau + * + * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorEnhancer\UndefinedMethodErrorEnhancer instead. + */ +class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface +{ + /** + * {@inheritdoc} + */ + public function handleError(array $error, FatalErrorException $exception) + { + preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches); + if (!$matches) { + return null; + } + + $className = $matches[1]; + $methodName = $matches[2]; + + $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className); + + if ('' === $methodName || !class_exists($className) || null === $methods = get_class_methods($className)) { + // failed to get the class or its methods on which an unknown method was called (for example on an anonymous class) + return new UndefinedMethodException($message, $exception); + } + + $candidates = []; + foreach ($methods as $definedMethodName) { + $lev = levenshtein($methodName, $definedMethodName); + if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { + $candidates[] = $definedMethodName; + } + } + + if ($candidates) { + sort($candidates); + $last = array_pop($candidates).'"?'; + if ($candidates) { + $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last; + } else { + $candidates = '"'.$last; + } + + $message .= "\nDid you mean to call ".$candidates; + } + + return new UndefinedMethodException($message, $exception); + } +} diff --git a/www/multitube/vendor/symfony/debug/LICENSE b/www/multitube/vendor/symfony/debug/LICENSE new file mode 100644 index 0000000..9ff2d0d --- /dev/null +++ b/www/multitube/vendor/symfony/debug/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2021 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/symfony/debug/README.md b/www/multitube/vendor/symfony/debug/README.md new file mode 100644 index 0000000..90b36f0 --- /dev/null +++ b/www/multitube/vendor/symfony/debug/README.md @@ -0,0 +1,30 @@ +Debug Component +=============== + +**CAUTION**: this component is deprecated since Symfony 4.4. Instead, use the +[ErrorHandler component](https://github.com/symfony/symfony/tree/master/src/Symfony/Component/ErrorHandler). + +----- + +The Debug component provides tools to ease debugging PHP code. + +Getting Started +--------------- + +``` +$ composer install symfony/debug +``` + +```php +use Symfony\Component\Debug\Debug; + +Debug::enable(); +``` + +Resources +--------- + + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/www/multitube/vendor/symfony/debug/composer.json b/www/multitube/vendor/symfony/debug/composer.json new file mode 100644 index 0000000..a364eb7 --- /dev/null +++ b/www/multitube/vendor/symfony/debug/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/debug", + "type": "library", + "description": "Provides tools to ease debugging PHP code", + "keywords": [], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1.3", + "psr/log": "~1.0", + "symfony/polyfill-php80": "^1.15" + }, + "conflict": { + "symfony/http-kernel": "<3.4" + }, + "require-dev": { + "symfony/http-kernel": "^3.4|^4.0|^5.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Debug\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev" +} diff --git a/www/multitube/vendor/symfony/deprecation-contracts/.gitignore b/www/multitube/vendor/symfony/deprecation-contracts/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/www/multitube/vendor/symfony/deprecation-contracts/CHANGELOG.md b/www/multitube/vendor/symfony/deprecation-contracts/CHANGELOG.md new file mode 100644 index 0000000..e984777 --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/CHANGELOG.md @@ -0,0 +1,5 @@ +CHANGELOG +========= + +The changelog is maintained for all Symfony contracts at the following URL: +https://github.com/symfony/contracts/blob/master/CHANGELOG.md diff --git a/www/multitube/vendor/symfony/deprecation-contracts/LICENSE b/www/multitube/vendor/symfony/deprecation-contracts/LICENSE new file mode 100644 index 0000000..5593b1d --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/symfony/deprecation-contracts/README.md b/www/multitube/vendor/symfony/deprecation-contracts/README.md new file mode 100644 index 0000000..4957933 --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/README.md @@ -0,0 +1,26 @@ +Symfony Deprecation Contracts +============================= + +A generic function and convention to trigger deprecation notices. + +This package provides a single global function named `trigger_deprecation()` that triggers silenced deprecation notices. + +By using a custom PHP error handler such as the one provided by the Symfony ErrorHandler component, +the triggered deprecations can be caught and logged for later discovery, both on dev and prod environments. + +The function requires at least 3 arguments: + - the name of the Composer package that is triggering the deprecation + - the version of the package that introduced the deprecation + - the message of the deprecation + - more arguments can be provided: they will be inserted in the message using `printf()` formatting + +Example: +```php +trigger_deprecation('symfony/blockchain', '8.9', 'Using "%s" is deprecated, use "%s" instead.', 'bitcoin', 'fabcoin'); +``` + +This will generate the following message: +`Since symfony/blockchain 8.9: Using "bitcoin" is deprecated, use "fabcoin" instead.` + +While not necessarily recommended, the deprecation notices can be completely ignored by declaring an empty +`function trigger_deprecation() {}` in your application. diff --git a/www/multitube/vendor/symfony/deprecation-contracts/composer.json b/www/multitube/vendor/symfony/deprecation-contracts/composer.json new file mode 100644 index 0000000..052541c --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/composer.json @@ -0,0 +1,35 @@ +{ + "name": "symfony/deprecation-contracts", + "type": "library", + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=7.1" + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + } +} diff --git a/www/multitube/vendor/symfony/deprecation-contracts/function.php b/www/multitube/vendor/symfony/deprecation-contracts/function.php new file mode 100644 index 0000000..d437150 --- /dev/null +++ b/www/multitube/vendor/symfony/deprecation-contracts/function.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +if (!function_exists('trigger_deprecation')) { + /** + * Triggers a silenced deprecation notice. + * + * @param string $package The name of the Composer package that is triggering the deprecation + * @param string $version The version of the package that introduced the deprecation + * @param string $message The message of the deprecation + * @param mixed ...$args Values to insert in the message using printf() formatting + * + * @author Nicolas Grekas + */ + function trigger_deprecation(string $package, string $version, string $message, ...$args): void + { + @trigger_error(($package || $version ? "Since $package $version: " : '').($args ? vsprintf($message, $args) : $message), \E_USER_DEPRECATED); + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/.gitignore b/www/multitube/vendor/symfony/dom-crawler/.gitignore new file mode 100644 index 0000000..c49a5d8 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/www/multitube/vendor/symfony/dom-crawler/AbstractUriElement.php b/www/multitube/vendor/symfony/dom-crawler/AbstractUriElement.php new file mode 100644 index 0000000..97604bc --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/AbstractUriElement.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +/** + * Any HTML element that can link to an URI. + * + * @author Fabien Potencier + */ +abstract class AbstractUriElement +{ + /** + * @var \DOMElement + */ + protected $node; + + /** + * @var string The method to use for the element + */ + protected $method; + + /** + * @var string The URI of the page where the element is embedded (or the base href) + */ + protected $currentUri; + + /** + * @param \DOMElement $node A \DOMElement instance + * @param string $currentUri The URI of the page where the link is embedded (or the base href) + * @param string $method The method to use for the link (get by default) + * + * @throws \InvalidArgumentException if the node is not a link + */ + public function __construct(\DOMElement $node, $currentUri, $method = 'GET') + { + if (!\in_array(strtolower(substr($currentUri, 0, 4)), ['http', 'file'])) { + throw new \InvalidArgumentException(sprintf('Current URI must be an absolute URL ("%s").', $currentUri)); + } + + $this->setNode($node); + $this->method = $method ? strtoupper($method) : null; + $this->currentUri = $currentUri; + } + + /** + * Gets the node associated with this link. + * + * @return \DOMElement A \DOMElement instance + */ + public function getNode() + { + return $this->node; + } + + /** + * Gets the method associated with this link. + * + * @return string The method + */ + public function getMethod() + { + return $this->method; + } + + /** + * Gets the URI associated with this link. + * + * @return string The URI + */ + public function getUri() + { + $uri = trim($this->getRawUri()); + + // absolute URL? + if (null !== parse_url($uri, \PHP_URL_SCHEME)) { + return $uri; + } + + // empty URI + if (!$uri) { + return $this->currentUri; + } + + // an anchor + if ('#' === $uri[0]) { + return $this->cleanupAnchor($this->currentUri).$uri; + } + + $baseUri = $this->cleanupUri($this->currentUri); + + if ('?' === $uri[0]) { + return $baseUri.$uri; + } + + // absolute URL with relative schema + if (0 === strpos($uri, '//')) { + return preg_replace('#^([^/]*)//.*$#', '$1', $baseUri).$uri; + } + + $baseUri = preg_replace('#^(.*?//[^/]*)(?:\/.*)?$#', '$1', $baseUri); + + // absolute path + if ('/' === $uri[0]) { + return $baseUri.$uri; + } + + // relative path + $path = parse_url(substr($this->currentUri, \strlen($baseUri)), \PHP_URL_PATH); + $path = $this->canonicalizePath(substr($path, 0, strrpos($path, '/')).'/'.$uri); + + return $baseUri.('' === $path || '/' !== $path[0] ? '/' : '').$path; + } + + /** + * Returns raw URI data. + * + * @return string + */ + abstract protected function getRawUri(); + + /** + * Returns the canonicalized URI path (see RFC 3986, section 5.2.4). + * + * @param string $path URI path + * + * @return string + */ + protected function canonicalizePath($path) + { + if ('' === $path || '/' === $path) { + return $path; + } + + if ('.' === substr($path, -1)) { + $path .= '/'; + } + + $output = []; + + foreach (explode('/', $path) as $segment) { + if ('..' === $segment) { + array_pop($output); + } elseif ('.' !== $segment) { + $output[] = $segment; + } + } + + return implode('/', $output); + } + + /** + * Sets current \DOMElement instance. + * + * @param \DOMElement $node A \DOMElement instance + * + * @throws \LogicException If given node is not an anchor + */ + abstract protected function setNode(\DOMElement $node); + + /** + * Removes the query string and the anchor from the given uri. + * + * @param string $uri The uri to clean + * + * @return string + */ + private function cleanupUri($uri) + { + return $this->cleanupQuery($this->cleanupAnchor($uri)); + } + + /** + * Remove the query string from the uri. + * + * @param string $uri + * + * @return string + */ + private function cleanupQuery($uri) + { + if (false !== $pos = strpos($uri, '?')) { + return substr($uri, 0, $pos); + } + + return $uri; + } + + /** + * Remove the anchor from the uri. + * + * @param string $uri + * + * @return string + */ + private function cleanupAnchor($uri) + { + if (false !== $pos = strpos($uri, '#')) { + return substr($uri, 0, $pos); + } + + return $uri; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/CHANGELOG.md b/www/multitube/vendor/symfony/dom-crawler/CHANGELOG.md new file mode 100644 index 0000000..e65176f --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/CHANGELOG.md @@ -0,0 +1,53 @@ +CHANGELOG +========= + +3.1.0 +----- + +* All the URI parsing logic have been abstracted in the `AbstractUriElement` class. + The `Link` class is now a child of `AbstractUriElement`. +* Added an `Image` class to crawl images and parse their `src` attribute, + and `selectImage`, `image`, `images` methods in the `Crawler` (the image version of the equivalent `link` methods). + +2.5.0 +----- + +* [BC BREAK] The default value for checkbox and radio inputs without a value attribute have changed + from '1' to 'on' to match the HTML specification. +* [BC BREAK] The typehints on the `Link`, `Form` and `FormField` classes have been changed from + `\DOMNode` to `DOMElement`. Using any other type of `DOMNode` was triggering fatal errors in previous + versions. Code extending these classes will need to update the typehints when overwriting these methods. + +2.4.0 +----- + + * `Crawler::addXmlContent()` removes the default document namespace again if it's an only namespace. + * added support for automatic discovery and explicit registration of document + namespaces for `Crawler::filterXPath()` and `Crawler::filter()` + * improved content type guessing in `Crawler::addContent()` + * [BC BREAK] `Crawler::addXmlContent()` no longer removes the default document + namespace + +2.3.0 +----- + + * added Crawler::html() + * [BC BREAK] Crawler::each() and Crawler::reduce() now return Crawler instances instead of DomElement instances + * added schema relative URL support to links + * added support for HTML5 'form' attribute + +2.2.0 +----- + + * added a way to set raw path to the file in FileFormField - necessary for + simulating HTTP requests + +2.1.0 +----- + + * added support for the HTTP PATCH method + * refactored the Form class internals to support multi-dimensional fields + (the public API is backward compatible) + * added a way to get parsing errors for Crawler::addHtmlContent() and + Crawler::addXmlContent() via libxml functions + * added support for submitting a form without a submit button diff --git a/www/multitube/vendor/symfony/dom-crawler/Crawler.php b/www/multitube/vendor/symfony/dom-crawler/Crawler.php new file mode 100644 index 0000000..21f7fab --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Crawler.php @@ -0,0 +1,1169 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +use Symfony\Component\CssSelector\CssSelectorConverter; + +/** + * Crawler eases navigation of a list of \DOMNode objects. + * + * @author Fabien Potencier + */ +class Crawler implements \Countable, \IteratorAggregate +{ + protected $uri; + + /** + * @var string The default namespace prefix to be used with XPath and CSS expressions + */ + private $defaultNamespacePrefix = 'default'; + + /** + * @var array A map of manually registered namespaces + */ + private $namespaces = []; + + /** + * @var string The base href value + */ + private $baseHref; + + /** + * @var \DOMDocument|null + */ + private $document; + + /** + * @var \DOMNode[] + */ + private $nodes = []; + + /** + * Whether the Crawler contains HTML or XML content (used when converting CSS to XPath). + * + * @var bool + */ + private $isHtml = true; + + /** + * @param \DOMNodeList|\DOMNode|\DOMNode[]|string|null $node A Node to use as the base for the crawling + */ + public function __construct($node = null, $uri = null, $baseHref = null) + { + $this->uri = $uri; + $this->baseHref = $baseHref ?: $uri; + + $this->add($node); + } + + /** + * Returns the current URI. + * + * @return string + */ + public function getUri() + { + return $this->uri; + } + + /** + * Returns base href. + * + * @return string + */ + public function getBaseHref() + { + return $this->baseHref; + } + + /** + * Removes all the nodes. + */ + public function clear() + { + $this->nodes = []; + $this->document = null; + } + + /** + * Adds a node to the current list of nodes. + * + * This method uses the appropriate specialized add*() method based + * on the type of the argument. + * + * @param \DOMNodeList|\DOMNode|\DOMNode[]|string|null $node A node + * + * @throws \InvalidArgumentException when node is not the expected type + */ + public function add($node) + { + if ($node instanceof \DOMNodeList) { + $this->addNodeList($node); + } elseif ($node instanceof \DOMNode) { + $this->addNode($node); + } elseif (\is_array($node)) { + $this->addNodes($node); + } elseif (\is_string($node)) { + $this->addContent($node); + } elseif (null !== $node) { + throw new \InvalidArgumentException(sprintf('Expecting a DOMNodeList or DOMNode instance, an array, a string, or null, but got "%s".', \is_object($node) ? \get_class($node) : \gettype($node))); + } + } + + /** + * Adds HTML/XML content. + * + * If the charset is not set via the content type, it is assumed to be UTF-8, + * or ISO-8859-1 as a fallback, which is the default charset defined by the + * HTTP 1.1 specification. + * + * @param string $content A string to parse as HTML/XML + * @param string|null $type The content type of the string + */ + public function addContent($content, $type = null) + { + if (empty($type)) { + $type = 0 === strpos($content, ']+charset *= *["\']?([a-zA-Z\-0-9_:.]+)/i', $content, $matches)) { + $charset = $matches[1]; + } + + if (null === $charset) { + $charset = preg_match('//u', $content) ? 'UTF-8' : 'ISO-8859-1'; + } + + if ('x' === $xmlMatches[1]) { + $this->addXmlContent($content, $charset); + } else { + $this->addHtmlContent($content, $charset); + } + } + + /** + * Adds an HTML content to the list of nodes. + * + * The libxml errors are disabled when the content is parsed. + * + * If you want to get parsing errors, be sure to enable + * internal errors via libxml_use_internal_errors(true) + * and then, get the errors via libxml_get_errors(). Be + * sure to clear errors with libxml_clear_errors() afterward. + * + * @param string $content The HTML content + * @param string $charset The charset + */ + public function addHtmlContent($content, $charset = 'UTF-8') + { + $internalErrors = libxml_use_internal_errors(true); + if (\LIBXML_VERSION < 20900) { + $disableEntities = libxml_disable_entity_loader(true); + } + + $dom = new \DOMDocument('1.0', $charset); + $dom->validateOnParse = true; + + set_error_handler(function () { throw new \Exception(); }); + + try { + // Convert charset to HTML-entities to work around bugs in DOMDocument::loadHTML() + $content = mb_convert_encoding($content, 'HTML-ENTITIES', $charset); + } catch (\Exception $e) { + } catch (\ValueError $e) { + } finally { + restore_error_handler(); + } + + if ('' !== trim($content)) { + @$dom->loadHTML($content); + } + + libxml_use_internal_errors($internalErrors); + if (\LIBXML_VERSION < 20900) { + libxml_disable_entity_loader($disableEntities); + } + + $this->addDocument($dom); + + $base = $this->filterRelativeXPath('descendant-or-self::base')->extract(['href']); + + $baseHref = current($base); + if (\count($base) && !empty($baseHref)) { + if ($this->baseHref) { + $linkNode = $dom->createElement('a'); + $linkNode->setAttribute('href', $baseHref); + $link = new Link($linkNode, $this->baseHref); + $this->baseHref = $link->getUri(); + } else { + $this->baseHref = $baseHref; + } + } + } + + /** + * Adds an XML content to the list of nodes. + * + * The libxml errors are disabled when the content is parsed. + * + * If you want to get parsing errors, be sure to enable + * internal errors via libxml_use_internal_errors(true) + * and then, get the errors via libxml_get_errors(). Be + * sure to clear errors with libxml_clear_errors() afterward. + * + * @param string $content The XML content + * @param string $charset The charset + * @param int $options Bitwise OR of the libxml option constants + * LIBXML_PARSEHUGE is dangerous, see + * http://symfony.com/blog/security-release-symfony-2-0-17-released + */ + public function addXmlContent($content, $charset = 'UTF-8', $options = \LIBXML_NONET) + { + // remove the default namespace if it's the only namespace to make XPath expressions simpler + if (!preg_match('/xmlns:/', $content)) { + $content = str_replace('xmlns', 'ns', $content); + } + + $internalErrors = libxml_use_internal_errors(true); + if (\LIBXML_VERSION < 20900) { + $disableEntities = libxml_disable_entity_loader(true); + } + + $dom = new \DOMDocument('1.0', $charset); + $dom->validateOnParse = true; + + if ('' !== trim($content)) { + @$dom->loadXML($content, $options); + } + + libxml_use_internal_errors($internalErrors); + if (\LIBXML_VERSION < 20900) { + libxml_disable_entity_loader($disableEntities); + } + + $this->addDocument($dom); + + $this->isHtml = false; + } + + /** + * Adds a \DOMDocument to the list of nodes. + * + * @param \DOMDocument $dom A \DOMDocument instance + */ + public function addDocument(\DOMDocument $dom) + { + if ($dom->documentElement) { + $this->addNode($dom->documentElement); + } + } + + /** + * Adds a \DOMNodeList to the list of nodes. + * + * @param \DOMNodeList $nodes A \DOMNodeList instance + */ + public function addNodeList(\DOMNodeList $nodes) + { + foreach ($nodes as $node) { + if ($node instanceof \DOMNode) { + $this->addNode($node); + } + } + } + + /** + * Adds an array of \DOMNode instances to the list of nodes. + * + * @param \DOMNode[] $nodes An array of \DOMNode instances + */ + public function addNodes(array $nodes) + { + foreach ($nodes as $node) { + $this->add($node); + } + } + + /** + * Adds a \DOMNode instance to the list of nodes. + * + * @param \DOMNode $node A \DOMNode instance + */ + public function addNode(\DOMNode $node) + { + if ($node instanceof \DOMDocument) { + $node = $node->documentElement; + } + + if (null !== $this->document && $this->document !== $node->ownerDocument) { + throw new \InvalidArgumentException('Attaching DOM nodes from multiple documents in the same crawler is forbidden.'); + } + + if (null === $this->document) { + $this->document = $node->ownerDocument; + } + + // Don't add duplicate nodes in the Crawler + if (\in_array($node, $this->nodes, true)) { + return; + } + + $this->nodes[] = $node; + } + + /** + * Returns a node given its position in the node list. + * + * @param int $position The position + * + * @return static + */ + public function eq($position) + { + if (isset($this->nodes[$position])) { + return $this->createSubCrawler($this->nodes[$position]); + } + + return $this->createSubCrawler(null); + } + + /** + * Calls an anonymous function on each node of the list. + * + * The anonymous function receives the position and the node wrapped + * in a Crawler instance as arguments. + * + * Example: + * + * $crawler->filter('h1')->each(function ($node, $i) { + * return $node->text(); + * }); + * + * @param \Closure $closure An anonymous function + * + * @return array An array of values returned by the anonymous function + */ + public function each(\Closure $closure) + { + $data = []; + foreach ($this->nodes as $i => $node) { + $data[] = $closure($this->createSubCrawler($node), $i); + } + + return $data; + } + + /** + * Slices the list of nodes by $offset and $length. + * + * @param int $offset + * @param int $length + * + * @return static + */ + public function slice($offset = 0, $length = null) + { + return $this->createSubCrawler(\array_slice($this->nodes, $offset, $length)); + } + + /** + * Reduces the list of nodes by calling an anonymous function. + * + * To remove a node from the list, the anonymous function must return false. + * + * @param \Closure $closure An anonymous function + * + * @return static + */ + public function reduce(\Closure $closure) + { + $nodes = []; + foreach ($this->nodes as $i => $node) { + if (false !== $closure($this->createSubCrawler($node), $i)) { + $nodes[] = $node; + } + } + + return $this->createSubCrawler($nodes); + } + + /** + * Returns the first node of the current selection. + * + * @return static + */ + public function first() + { + return $this->eq(0); + } + + /** + * Returns the last node of the current selection. + * + * @return static + */ + public function last() + { + return $this->eq(\count($this->nodes) - 1); + } + + /** + * Returns the siblings nodes of the current selection. + * + * @return static + * + * @throws \InvalidArgumentException When current node is empty + */ + public function siblings() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + return $this->createSubCrawler($this->sibling($this->getNode(0)->parentNode->firstChild)); + } + + /** + * Returns the next siblings nodes of the current selection. + * + * @return static + * + * @throws \InvalidArgumentException When current node is empty + */ + public function nextAll() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + return $this->createSubCrawler($this->sibling($this->getNode(0))); + } + + /** + * Returns the previous sibling nodes of the current selection. + * + * @return static + * + * @throws \InvalidArgumentException + */ + public function previousAll() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + return $this->createSubCrawler($this->sibling($this->getNode(0), 'previousSibling')); + } + + /** + * Returns the parents nodes of the current selection. + * + * @return static + * + * @throws \InvalidArgumentException When current node is empty + */ + public function parents() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0); + $nodes = []; + + while ($node = $node->parentNode) { + if (\XML_ELEMENT_NODE === $node->nodeType) { + $nodes[] = $node; + } + } + + return $this->createSubCrawler($nodes); + } + + /** + * Returns the children nodes of the current selection. + * + * @return static + * + * @throws \InvalidArgumentException When current node is empty + */ + public function children() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0)->firstChild; + + return $this->createSubCrawler($node ? $this->sibling($node) : []); + } + + /** + * Returns the attribute value of the first node of the list. + * + * @param string $attribute The attribute name + * + * @return string|null The attribute value or null if the attribute does not exist + * + * @throws \InvalidArgumentException When current node is empty + */ + public function attr($attribute) + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0); + + return $node->hasAttribute($attribute) ? $node->getAttribute($attribute) : null; + } + + /** + * Returns the node name of the first node of the list. + * + * @return string The node name + * + * @throws \InvalidArgumentException When current node is empty + */ + public function nodeName() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + return $this->getNode(0)->nodeName; + } + + /** + * Returns the node value of the first node of the list. + * + * @return string The node value + * + * @throws \InvalidArgumentException When current node is empty + */ + public function text() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + return $this->getNode(0)->nodeValue; + } + + /** + * Returns the first node of the list as HTML. + * + * @return string The node html + * + * @throws \InvalidArgumentException When current node is empty + */ + public function html() + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $html = ''; + foreach ($this->getNode(0)->childNodes as $child) { + $html .= $child->ownerDocument->saveHTML($child); + } + + return $html; + } + + /** + * Evaluates an XPath expression. + * + * Since an XPath expression might evaluate to either a simple type or a \DOMNodeList, + * this method will return either an array of simple types or a new Crawler instance. + * + * @param string $xpath An XPath expression + * + * @return array|Crawler An array of evaluation results or a new Crawler instance + */ + public function evaluate($xpath) + { + if (null === $this->document) { + throw new \LogicException('Cannot evaluate the expression on an uninitialized crawler.'); + } + + $data = []; + $domxpath = $this->createDOMXPath($this->document, $this->findNamespacePrefixes($xpath)); + + foreach ($this->nodes as $node) { + $data[] = $domxpath->evaluate($xpath, $node); + } + + if (isset($data[0]) && $data[0] instanceof \DOMNodeList) { + return $this->createSubCrawler($data); + } + + return $data; + } + + /** + * Extracts information from the list of nodes. + * + * You can extract attributes or/and the node value (_text). + * + * Example: + * + * $crawler->filter('h1 a')->extract(['_text', 'href']); + * + * @param array $attributes An array of attributes + * + * @return array An array of extracted values + */ + public function extract($attributes) + { + $attributes = (array) $attributes; + $count = \count($attributes); + + $data = []; + foreach ($this->nodes as $node) { + $elements = []; + foreach ($attributes as $attribute) { + if ('_text' === $attribute) { + $elements[] = $node->nodeValue; + } else { + $elements[] = $node->getAttribute($attribute); + } + } + + $data[] = 1 === $count ? $elements[0] : $elements; + } + + return $data; + } + + /** + * Filters the list of nodes with an XPath expression. + * + * The XPath expression is evaluated in the context of the crawler, which + * is considered as a fake parent of the elements inside it. + * This means that a child selector "div" or "./div" will match only + * the div elements of the current crawler, not their children. + * + * @param string $xpath An XPath expression + * + * @return static + */ + public function filterXPath($xpath) + { + $xpath = $this->relativize($xpath); + + // If we dropped all expressions in the XPath while preparing it, there would be no match + if ('' === $xpath) { + return $this->createSubCrawler(null); + } + + return $this->filterRelativeXPath($xpath); + } + + /** + * Filters the list of nodes with a CSS selector. + * + * This method only works if you have installed the CssSelector Symfony Component. + * + * @param string $selector A CSS selector + * + * @return static + * + * @throws \RuntimeException if the CssSelector Component is not available + */ + public function filter($selector) + { + if (!class_exists(CssSelectorConverter::class)) { + throw new \RuntimeException('To filter with a CSS selector, install the CssSelector component ("composer require symfony/css-selector"). Or use filterXpath instead.'); + } + + $converter = new CssSelectorConverter($this->isHtml); + + // The CssSelector already prefixes the selector with descendant-or-self:: + return $this->filterRelativeXPath($converter->toXPath($selector)); + } + + /** + * Selects links by name or alt value for clickable images. + * + * @param string $value The link text + * + * @return static + */ + public function selectLink($value) + { + $xpath = sprintf('descendant-or-self::a[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) ', static::xpathLiteral(' '.$value.' ')). + sprintf('or ./img[contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)]]', static::xpathLiteral(' '.$value.' ')); + + return $this->filterRelativeXPath($xpath); + } + + /** + * Selects images by alt value. + * + * @param string $value The image alt + * + * @return static A new instance of Crawler with the filtered list of nodes + */ + public function selectImage($value) + { + $xpath = sprintf('descendant-or-self::img[contains(normalize-space(string(@alt)), %s)]', static::xpathLiteral($value)); + + return $this->filterRelativeXPath($xpath); + } + + /** + * Selects a button by name or alt value for images. + * + * @param string $value The button text + * + * @return static + */ + public function selectButton($value) + { + $translate = 'translate(@type, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")'; + $xpath = sprintf('descendant-or-self::input[((contains(%s, "submit") or contains(%1$s, "button")) and contains(concat(\' \', normalize-space(string(@value)), \' \'), %s)) ', $translate, static::xpathLiteral(' '.$value.' ')). + sprintf('or (contains(%s, "image") and contains(concat(\' \', normalize-space(string(@alt)), \' \'), %s)) or @id=%s or @name=%s] ', $translate, static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value), static::xpathLiteral($value)). + sprintf('| descendant-or-self::button[contains(concat(\' \', normalize-space(string(.)), \' \'), %s) or @id=%s or @name=%s]', static::xpathLiteral(' '.$value.' '), static::xpathLiteral($value), static::xpathLiteral($value)); + + return $this->filterRelativeXPath($xpath); + } + + /** + * Returns a Link object for the first node in the list. + * + * @param string $method The method for the link (get by default) + * + * @return Link A Link instance + * + * @throws \InvalidArgumentException If the current node list is empty or the selected node is not instance of DOMElement + */ + public function link($method = 'get') + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0); + + if (!$node instanceof \DOMElement) { + throw new \InvalidArgumentException(sprintf('The selected node should be instance of DOMElement, got "%s".', \get_class($node))); + } + + return new Link($node, $this->baseHref, $method); + } + + /** + * Returns an array of Link objects for the nodes in the list. + * + * @return Link[] An array of Link instances + * + * @throws \InvalidArgumentException If the current node list contains non-DOMElement instances + */ + public function links() + { + $links = []; + foreach ($this->nodes as $node) { + if (!$node instanceof \DOMElement) { + throw new \InvalidArgumentException(sprintf('The current node list should contain only DOMElement instances, "%s" found.', \get_class($node))); + } + + $links[] = new Link($node, $this->baseHref, 'get'); + } + + return $links; + } + + /** + * Returns an Image object for the first node in the list. + * + * @return Image An Image instance + * + * @throws \InvalidArgumentException If the current node list is empty + */ + public function image() + { + if (!\count($this)) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0); + + if (!$node instanceof \DOMElement) { + throw new \InvalidArgumentException(sprintf('The selected node should be instance of DOMElement, got "%s".', \get_class($node))); + } + + return new Image($node, $this->baseHref); + } + + /** + * Returns an array of Image objects for the nodes in the list. + * + * @return Image[] An array of Image instances + */ + public function images() + { + $images = []; + foreach ($this as $node) { + if (!$node instanceof \DOMElement) { + throw new \InvalidArgumentException(sprintf('The current node list should contain only DOMElement instances, "%s" found.', \get_class($node))); + } + + $images[] = new Image($node, $this->baseHref); + } + + return $images; + } + + /** + * Returns a Form object for the first node in the list. + * + * @param array $values An array of values for the form fields + * @param string $method The method for the form + * + * @return Form A Form instance + * + * @throws \InvalidArgumentException If the current node list is empty or the selected node is not instance of DOMElement + */ + public function form(array $values = null, $method = null) + { + if (!$this->nodes) { + throw new \InvalidArgumentException('The current node list is empty.'); + } + + $node = $this->getNode(0); + + if (!$node instanceof \DOMElement) { + throw new \InvalidArgumentException(sprintf('The selected node should be instance of DOMElement, got "%s".', \get_class($node))); + } + + $form = new Form($node, $this->uri, $method, $this->baseHref); + + if (null !== $values) { + $form->setValues($values); + } + + return $form; + } + + /** + * Overloads a default namespace prefix to be used with XPath and CSS expressions. + * + * @param string $prefix + */ + public function setDefaultNamespacePrefix($prefix) + { + $this->defaultNamespacePrefix = $prefix; + } + + /** + * @param string $prefix + * @param string $namespace + */ + public function registerNamespace($prefix, $namespace) + { + $this->namespaces[$prefix] = $namespace; + } + + /** + * Converts string for XPath expressions. + * + * Escaped characters are: quotes (") and apostrophe ('). + * + * Examples: + * + * echo Crawler::xpathLiteral('foo " bar'); + * //prints 'foo " bar' + * + * echo Crawler::xpathLiteral("foo ' bar"); + * //prints "foo ' bar" + * + * echo Crawler::xpathLiteral('a\'b"c'); + * //prints concat('a', "'", 'b"c') + * + * @param string $s String to be escaped + * + * @return string Converted string + */ + public static function xpathLiteral($s) + { + if (false === strpos($s, "'")) { + return sprintf("'%s'", $s); + } + + if (false === strpos($s, '"')) { + return sprintf('"%s"', $s); + } + + $string = $s; + $parts = []; + while (true) { + if (false !== $pos = strpos($string, "'")) { + $parts[] = sprintf("'%s'", substr($string, 0, $pos)); + $parts[] = "\"'\""; + $string = substr($string, $pos + 1); + } else { + $parts[] = "'$string'"; + break; + } + } + + return sprintf('concat(%s)', implode(', ', $parts)); + } + + /** + * Filters the list of nodes with an XPath expression. + * + * The XPath expression should already be processed to apply it in the context of each node. + * + * @param string $xpath + * + * @return static + */ + private function filterRelativeXPath($xpath) + { + $prefixes = $this->findNamespacePrefixes($xpath); + + $crawler = $this->createSubCrawler(null); + + foreach ($this->nodes as $node) { + $domxpath = $this->createDOMXPath($node->ownerDocument, $prefixes); + $crawler->add($domxpath->query($xpath, $node)); + } + + return $crawler; + } + + /** + * Make the XPath relative to the current context. + * + * The returned XPath will match elements matching the XPath inside the current crawler + * when running in the context of a node of the crawler. + * + * @param string $xpath + * + * @return string + */ + private function relativize($xpath) + { + $expressions = []; + + // An expression which will never match to replace expressions which cannot match in the crawler + // We cannot drop + $nonMatchingExpression = 'a[name() = "b"]'; + + $xpathLen = \strlen($xpath); + $openedBrackets = 0; + $startPosition = strspn($xpath, " \t\n\r\0\x0B"); + + for ($i = $startPosition; $i <= $xpathLen; ++$i) { + $i += strcspn($xpath, '"\'[]|', $i); + + if ($i < $xpathLen) { + switch ($xpath[$i]) { + case '"': + case "'": + if (false === $i = strpos($xpath, $xpath[$i], $i + 1)) { + return $xpath; // The XPath expression is invalid + } + continue 2; + case '[': + ++$openedBrackets; + continue 2; + case ']': + --$openedBrackets; + continue 2; + } + } + if ($openedBrackets) { + continue; + } + + if ($startPosition < $xpathLen && '(' === $xpath[$startPosition]) { + // If the union is inside some braces, we need to preserve the opening braces and apply + // the change only inside it. + $j = 1 + strspn($xpath, "( \t\n\r\0\x0B", $startPosition + 1); + $parenthesis = substr($xpath, $startPosition, $j); + $startPosition += $j; + } else { + $parenthesis = ''; + } + $expression = rtrim(substr($xpath, $startPosition, $i - $startPosition)); + + if (0 === strpos($expression, 'self::*/')) { + $expression = './'.substr($expression, 8); + } + + // add prefix before absolute element selector + if ('' === $expression) { + $expression = $nonMatchingExpression; + } elseif (0 === strpos($expression, '//')) { + $expression = 'descendant-or-self::'.substr($expression, 2); + } elseif (0 === strpos($expression, './/')) { + $expression = 'descendant-or-self::'.substr($expression, 3); + } elseif (0 === strpos($expression, './')) { + $expression = 'self::'.substr($expression, 2); + } elseif (0 === strpos($expression, 'child::')) { + $expression = 'self::'.substr($expression, 7); + } elseif ('/' === $expression[0] || '.' === $expression[0] || 0 === strpos($expression, 'self::')) { + $expression = $nonMatchingExpression; + } elseif (0 === strpos($expression, 'descendant::')) { + $expression = 'descendant-or-self::'.substr($expression, 12); + } elseif (preg_match('/^(ancestor|ancestor-or-self|attribute|following|following-sibling|namespace|parent|preceding|preceding-sibling)::/', $expression)) { + // the fake root has no parent, preceding or following nodes and also no attributes (even no namespace attributes) + $expression = $nonMatchingExpression; + } elseif (0 !== strpos($expression, 'descendant-or-self::')) { + $expression = 'self::'.$expression; + } + $expressions[] = $parenthesis.$expression; + + if ($i === $xpathLen) { + return implode(' | ', $expressions); + } + + $i += strspn($xpath, " \t\n\r\0\x0B", $i + 1); + $startPosition = $i + 1; + } + + return $xpath; // The XPath expression is invalid + } + + /** + * @param int $position + * + * @return \DOMNode|null + */ + public function getNode($position) + { + return isset($this->nodes[$position]) ? $this->nodes[$position] : null; + } + + /** + * @return int + */ + public function count() + { + return \count($this->nodes); + } + + /** + * @return \ArrayIterator|\DOMNode[] + */ + public function getIterator() + { + return new \ArrayIterator($this->nodes); + } + + /** + * @param \DOMElement $node + * @param string $siblingDir + * + * @return array + */ + protected function sibling($node, $siblingDir = 'nextSibling') + { + $nodes = []; + + do { + if ($node !== $this->getNode(0) && 1 === $node->nodeType) { + $nodes[] = $node; + } + } while ($node = $node->$siblingDir); + + return $nodes; + } + + /** + * @return \DOMXPath + * + * @throws \InvalidArgumentException + */ + private function createDOMXPath(\DOMDocument $document, array $prefixes = []) + { + $domxpath = new \DOMXPath($document); + + foreach ($prefixes as $prefix) { + $namespace = $this->discoverNamespace($domxpath, $prefix); + if (null !== $namespace) { + $domxpath->registerNamespace($prefix, $namespace); + } + } + + return $domxpath; + } + + /** + * @param string $prefix + * + * @return string|null + * + * @throws \InvalidArgumentException + */ + private function discoverNamespace(\DOMXPath $domxpath, $prefix) + { + if (isset($this->namespaces[$prefix])) { + return $this->namespaces[$prefix]; + } + + // ask for one namespace, otherwise we'd get a collection with an item for each node + $namespaces = $domxpath->query(sprintf('(//namespace::*[name()="%s"])[last()]', $this->defaultNamespacePrefix === $prefix ? '' : $prefix)); + + return ($node = $namespaces->item(0)) ? $node->nodeValue : null; + } + + /** + * @param string $xpath + * + * @return array + */ + private function findNamespacePrefixes($xpath) + { + if (preg_match_all('/(?P[a-z_][a-z_0-9\-\.]*+):[^"\/:]/i', $xpath, $matches)) { + return array_unique($matches['prefix']); + } + + return []; + } + + /** + * Creates a crawler for some subnodes. + * + * @param \DOMNodeList|\DOMNode|\DOMNode[]|string|null $nodes + * + * @return static + */ + private function createSubCrawler($nodes) + { + $crawler = new static($nodes, $this->uri, $this->baseHref); + $crawler->isHtml = $this->isHtml; + $crawler->document = $this->document; + $crawler->namespaces = $this->namespaces; + + return $crawler; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Field/ChoiceFormField.php b/www/multitube/vendor/symfony/dom-crawler/Field/ChoiceFormField.php new file mode 100644 index 0000000..a7d2b84 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Field/ChoiceFormField.php @@ -0,0 +1,320 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Field; + +/** + * ChoiceFormField represents a choice form field. + * + * It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs. + * + * @author Fabien Potencier + */ +class ChoiceFormField extends FormField +{ + /** + * @var string + */ + private $type; + /** + * @var bool + */ + private $multiple; + /** + * @var array + */ + private $options; + /** + * @var bool + */ + private $validationDisabled = false; + + /** + * Returns true if the field should be included in the submitted values. + * + * @return bool true if the field should be included in the submitted values, false otherwise + */ + public function hasValue() + { + // don't send a value for unchecked checkboxes + if (\in_array($this->type, ['checkbox', 'radio']) && null === $this->value) { + return false; + } + + return true; + } + + /** + * Check if the current selected option is disabled. + * + * @return bool + */ + public function isDisabled() + { + if (parent::isDisabled() && 'select' === $this->type) { + return true; + } + + foreach ($this->options as $option) { + if ($option['value'] == $this->value && $option['disabled']) { + return true; + } + } + + return false; + } + + /** + * Sets the value of the field. + * + * @param string|array $value The value of the field + */ + public function select($value) + { + $this->setValue($value); + } + + /** + * Ticks a checkbox. + * + * @throws \LogicException When the type provided is not correct + */ + public function tick() + { + if ('checkbox' !== $this->type) { + throw new \LogicException(sprintf('You cannot tick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); + } + + $this->setValue(true); + } + + /** + * Unticks a checkbox. + * + * @throws \LogicException When the type provided is not correct + */ + public function untick() + { + if ('checkbox' !== $this->type) { + throw new \LogicException(sprintf('You cannot untick "%s" as it is not a checkbox (%s).', $this->name, $this->type)); + } + + $this->setValue(false); + } + + /** + * Sets the value of the field. + * + * @param string|array|bool $value The value of the field + * + * @throws \InvalidArgumentException When value type provided is not correct + */ + public function setValue($value) + { + if ('checkbox' === $this->type && false === $value) { + // uncheck + $this->value = null; + } elseif ('checkbox' === $this->type && true === $value) { + // check + $this->value = $this->options[0]['value']; + } else { + if (\is_array($value)) { + if (!$this->multiple) { + throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name)); + } + + foreach ($value as $v) { + if (!$this->containsOption($v, $this->options)) { + throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: "%s").', $this->name, $v, implode('", "', $this->availableOptionValues()))); + } + } + } elseif (!$this->containsOption($value, $this->options)) { + throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: "%s").', $this->name, $value, implode('", "', $this->availableOptionValues()))); + } + + if ($this->multiple) { + $value = (array) $value; + } + + if (\is_array($value)) { + $this->value = $value; + } else { + parent::setValue($value); + } + } + } + + /** + * Adds a choice to the current ones. + * + * @throws \LogicException When choice provided is not multiple nor radio + * + * @internal + */ + public function addChoice(\DOMElement $node) + { + if (!$this->multiple && 'radio' !== $this->type) { + throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name)); + } + + $option = $this->buildOptionValue($node); + $this->options[] = $option; + + if ($node->hasAttribute('checked')) { + $this->value = $option['value']; + } + } + + /** + * Returns the type of the choice field (radio, select, or checkbox). + * + * @return string The type + */ + public function getType() + { + return $this->type; + } + + /** + * Returns true if the field accepts multiple values. + * + * @return bool true if the field accepts multiple values, false otherwise + */ + public function isMultiple() + { + return $this->multiple; + } + + /** + * Initializes the form field. + * + * @throws \LogicException When node type is incorrect + */ + protected function initialize() + { + if ('input' !== $this->node->nodeName && 'select' !== $this->node->nodeName) { + throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName)); + } + + if ('input' === $this->node->nodeName && 'checkbox' !== strtolower($this->node->getAttribute('type')) && 'radio' !== strtolower($this->node->getAttribute('type'))) { + throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is "%s").', $this->node->getAttribute('type'))); + } + + $this->value = null; + $this->options = []; + $this->multiple = false; + + if ('input' == $this->node->nodeName) { + $this->type = strtolower($this->node->getAttribute('type')); + $optionValue = $this->buildOptionValue($this->node); + $this->options[] = $optionValue; + + if ($this->node->hasAttribute('checked')) { + $this->value = $optionValue['value']; + } + } else { + $this->type = 'select'; + if ($this->node->hasAttribute('multiple')) { + $this->multiple = true; + $this->value = []; + $this->name = str_replace('[]', '', $this->name); + } + + $found = false; + foreach ($this->xpath->query('descendant::option', $this->node) as $option) { + $optionValue = $this->buildOptionValue($option); + $this->options[] = $optionValue; + + if ($option->hasAttribute('selected')) { + $found = true; + if ($this->multiple) { + $this->value[] = $optionValue['value']; + } else { + $this->value = $optionValue['value']; + } + } + } + + // if no option is selected and if it is a simple select box, take the first option as the value + if (!$found && !$this->multiple && !empty($this->options)) { + $this->value = $this->options[0]['value']; + } + } + } + + /** + * Returns option value with associated disabled flag. + * + * @return array + */ + private function buildOptionValue(\DOMElement $node) + { + $option = []; + + $defaultDefaultValue = 'select' === $this->node->nodeName ? '' : 'on'; + $defaultValue = (isset($node->nodeValue) && !empty($node->nodeValue)) ? $node->nodeValue : $defaultDefaultValue; + $option['value'] = $node->hasAttribute('value') ? $node->getAttribute('value') : $defaultValue; + $option['disabled'] = $node->hasAttribute('disabled'); + + return $option; + } + + /** + * Checks whether given value is in the existing options. + * + * @param string $optionValue + * @param array $options + * + * @return bool + */ + public function containsOption($optionValue, $options) + { + if ($this->validationDisabled) { + return true; + } + + foreach ($options as $option) { + if ($option['value'] == $optionValue) { + return true; + } + } + + return false; + } + + /** + * Returns list of available field options. + * + * @return array + */ + public function availableOptionValues() + { + $values = []; + + foreach ($this->options as $option) { + $values[] = $option['value']; + } + + return $values; + } + + /** + * Disables the internal validation of the field. + * + * @return self + */ + public function disableValidation() + { + $this->validationDisabled = true; + + return $this; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Field/FileFormField.php b/www/multitube/vendor/symfony/dom-crawler/Field/FileFormField.php new file mode 100644 index 0000000..3d0b22f --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Field/FileFormField.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Field; + +/** + * FileFormField represents a file form field (an HTML file input tag). + * + * @author Fabien Potencier + */ +class FileFormField extends FormField +{ + /** + * Sets the PHP error code associated with the field. + * + * @param int $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION) + * + * @throws \InvalidArgumentException When error code doesn't exist + */ + public function setErrorCode($error) + { + $codes = [\UPLOAD_ERR_INI_SIZE, \UPLOAD_ERR_FORM_SIZE, \UPLOAD_ERR_PARTIAL, \UPLOAD_ERR_NO_FILE, \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_CANT_WRITE, \UPLOAD_ERR_EXTENSION]; + if (!\in_array($error, $codes)) { + throw new \InvalidArgumentException(sprintf('The error code "%s" is not valid.', $error)); + } + + $this->value = ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0]; + } + + /** + * Sets the value of the field. + * + * @param string $value The value of the field + */ + public function upload($value) + { + $this->setValue($value); + } + + /** + * Sets the value of the field. + * + * @param string|null $value The value of the field + */ + public function setValue($value) + { + if (null !== $value && is_readable($value)) { + $error = \UPLOAD_ERR_OK; + $size = filesize($value); + $info = pathinfo($value); + $name = $info['basename']; + + // copy to a tmp location + $tmp = sys_get_temp_dir().'/'.strtr(substr(base64_encode(hash('sha256', uniqid(mt_rand(), true), true)), 0, 7), '/', '_'); + if (\array_key_exists('extension', $info)) { + $tmp .= '.'.$info['extension']; + } + if (is_file($tmp)) { + unlink($tmp); + } + copy($value, $tmp); + $value = $tmp; + } else { + $error = \UPLOAD_ERR_NO_FILE; + $size = 0; + $name = ''; + $value = ''; + } + + $this->value = ['name' => $name, 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size]; + } + + /** + * Sets path to the file as string for simulating HTTP request. + * + * @param string $path The path to the file + */ + public function setFilePath($path) + { + parent::setValue($path); + } + + /** + * Initializes the form field. + * + * @throws \LogicException When node type is incorrect + */ + protected function initialize() + { + if ('input' !== $this->node->nodeName) { + throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName)); + } + + if ('file' !== strtolower($this->node->getAttribute('type'))) { + throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is "%s").', $this->node->getAttribute('type'))); + } + + $this->setValue(null); + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Field/FormField.php b/www/multitube/vendor/symfony/dom-crawler/Field/FormField.php new file mode 100644 index 0000000..0bc4f54 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Field/FormField.php @@ -0,0 +1,133 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Field; + +/** + * FormField is the abstract class for all form fields. + * + * @author Fabien Potencier + */ +abstract class FormField +{ + /** + * @var \DOMElement + */ + protected $node; + /** + * @var string + */ + protected $name; + /** + * @var string + */ + protected $value; + /** + * @var \DOMDocument + */ + protected $document; + /** + * @var \DOMXPath + */ + protected $xpath; + /** + * @var bool + */ + protected $disabled; + + /** + * @param \DOMElement $node The node associated with this field + */ + public function __construct(\DOMElement $node) + { + $this->node = $node; + $this->name = $node->getAttribute('name'); + $this->xpath = new \DOMXPath($node->ownerDocument); + + $this->initialize(); + } + + /** + * Returns the label tag associated to the field or null if none. + * + * @return \DOMElement|null + */ + public function getLabel() + { + $xpath = new \DOMXPath($this->node->ownerDocument); + + if ($this->node->hasAttribute('id')) { + $labels = $xpath->query(sprintf('descendant::label[@for="%s"]', $this->node->getAttribute('id'))); + if ($labels->length > 0) { + return $labels->item(0); + } + } + + $labels = $xpath->query('ancestor::label[1]', $this->node); + + return $labels->length > 0 ? $labels->item(0) : null; + } + + /** + * Returns the name of the field. + * + * @return string The name of the field + */ + public function getName() + { + return $this->name; + } + + /** + * Gets the value of the field. + * + * @return string|array The value of the field + */ + public function getValue() + { + return $this->value; + } + + /** + * Sets the value of the field. + * + * @param string|array|bool|null $value The value of the field + */ + public function setValue($value) + { + $this->value = (string) $value; + } + + /** + * Returns true if the field should be included in the submitted values. + * + * @return bool true if the field should be included in the submitted values, false otherwise + */ + public function hasValue() + { + return true; + } + + /** + * Check if the current field is disabled. + * + * @return bool + */ + public function isDisabled() + { + return $this->node->hasAttribute('disabled'); + } + + /** + * Initializes the form field. + */ + abstract protected function initialize(); +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Field/InputFormField.php b/www/multitube/vendor/symfony/dom-crawler/Field/InputFormField.php new file mode 100644 index 0000000..1c3c84d --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Field/InputFormField.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Field; + +/** + * InputFormField represents an input form field (an HTML input tag). + * + * For inputs with type of file, checkbox, or radio, there are other more + * specialized classes (cf. FileFormField and ChoiceFormField). + * + * @author Fabien Potencier + */ +class InputFormField extends FormField +{ + /** + * Initializes the form field. + * + * @throws \LogicException When node type is incorrect + */ + protected function initialize() + { + if ('input' !== $this->node->nodeName && 'button' !== $this->node->nodeName) { + throw new \LogicException(sprintf('An InputFormField can only be created from an input or button tag (%s given).', $this->node->nodeName)); + } + + $type = strtolower($this->node->getAttribute('type')); + if ('checkbox' === $type) { + throw new \LogicException('Checkboxes should be instances of ChoiceFormField.'); + } + + if ('file' === $type) { + throw new \LogicException('File inputs should be instances of FileFormField.'); + } + + $this->value = $this->node->getAttribute('value'); + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Field/TextareaFormField.php b/www/multitube/vendor/symfony/dom-crawler/Field/TextareaFormField.php new file mode 100644 index 0000000..15526e1 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Field/TextareaFormField.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Field; + +/** + * TextareaFormField represents a textarea form field (an HTML textarea tag). + * + * @author Fabien Potencier + */ +class TextareaFormField extends FormField +{ + /** + * Initializes the form field. + * + * @throws \LogicException When node type is incorrect + */ + protected function initialize() + { + if ('textarea' !== $this->node->nodeName) { + throw new \LogicException(sprintf('A TextareaFormField can only be created from a textarea tag (%s given).', $this->node->nodeName)); + } + + $this->value = ''; + foreach ($this->node->childNodes as $node) { + $this->value .= $node->wholeText; + } + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Form.php b/www/multitube/vendor/symfony/dom-crawler/Form.php new file mode 100644 index 0000000..7c85ec6 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Form.php @@ -0,0 +1,489 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +use Symfony\Component\DomCrawler\Field\ChoiceFormField; +use Symfony\Component\DomCrawler\Field\FormField; + +/** + * Form represents an HTML form. + * + * @author Fabien Potencier + */ +class Form extends Link implements \ArrayAccess +{ + /** + * @var \DOMElement + */ + private $button; + + /** + * @var FormFieldRegistry + */ + private $fields; + + /** + * @var string + */ + private $baseHref; + + /** + * @param \DOMElement $node A \DOMElement instance + * @param string $currentUri The URI of the page where the form is embedded + * @param string $method The method to use for the link (if null, it defaults to the method defined by the form) + * @param string $baseHref The URI of the used for relative links, but not for empty action + * + * @throws \LogicException if the node is not a button inside a form tag + */ + public function __construct(\DOMElement $node, $currentUri, $method = null, $baseHref = null) + { + parent::__construct($node, $currentUri, $method); + $this->baseHref = $baseHref; + + $this->initialize(); + } + + /** + * Gets the form node associated with this form. + * + * @return \DOMElement A \DOMElement instance + */ + public function getFormNode() + { + return $this->node; + } + + /** + * Sets the value of the fields. + * + * @param array $values An array of field values + * + * @return $this + */ + public function setValues(array $values) + { + foreach ($values as $name => $value) { + $this->fields->set($name, $value); + } + + return $this; + } + + /** + * Gets the field values. + * + * The returned array does not include file fields (@see getFiles). + * + * @return array An array of field values + */ + public function getValues() + { + $values = []; + foreach ($this->fields->all() as $name => $field) { + if ($field->isDisabled()) { + continue; + } + + if (!$field instanceof Field\FileFormField && $field->hasValue()) { + $values[$name] = $field->getValue(); + } + } + + return $values; + } + + /** + * Gets the file field values. + * + * @return array An array of file field values + */ + public function getFiles() + { + if (!\in_array($this->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) { + return []; + } + + $files = []; + + foreach ($this->fields->all() as $name => $field) { + if ($field->isDisabled()) { + continue; + } + + if ($field instanceof Field\FileFormField) { + $files[$name] = $field->getValue(); + } + } + + return $files; + } + + /** + * Gets the field values as PHP. + * + * This method converts fields with the array notation + * (like foo[bar] to arrays) like PHP does. + * + * @return array An array of field values + */ + public function getPhpValues() + { + $values = []; + foreach ($this->getValues() as $name => $value) { + $qs = http_build_query([$name => $value], '', '&'); + if (!empty($qs)) { + parse_str($qs, $expandedValue); + $varName = substr($name, 0, \strlen(key($expandedValue))); + $values = array_replace_recursive($values, [$varName => current($expandedValue)]); + } + } + + return $values; + } + + /** + * Gets the file field values as PHP. + * + * This method converts fields with the array notation + * (like foo[bar] to arrays) like PHP does. + * The returned array is consistent with the array for field values + * (@see getPhpValues), rather than uploaded files found in $_FILES. + * For a compound file field foo[bar] it will create foo[bar][name], + * instead of foo[name][bar] which would be found in $_FILES. + * + * @return array An array of file field values + */ + public function getPhpFiles() + { + $values = []; + foreach ($this->getFiles() as $name => $value) { + $qs = http_build_query([$name => $value], '', '&'); + if (!empty($qs)) { + parse_str($qs, $expandedValue); + $varName = substr($name, 0, \strlen(key($expandedValue))); + + array_walk_recursive( + $expandedValue, + function (&$value, $key) { + if (ctype_digit($value) && ('size' === $key || 'error' === $key)) { + $value = (int) $value; + } + } + ); + + reset($expandedValue); + + $values = array_replace_recursive($values, [$varName => current($expandedValue)]); + } + } + + return $values; + } + + /** + * Gets the URI of the form. + * + * The returned URI is not the same as the form "action" attribute. + * This method merges the value if the method is GET to mimics + * browser behavior. + * + * @return string The URI + */ + public function getUri() + { + $uri = parent::getUri(); + + if (!\in_array($this->getMethod(), ['POST', 'PUT', 'DELETE', 'PATCH'])) { + $query = parse_url($uri, \PHP_URL_QUERY); + $currentParameters = []; + if ($query) { + parse_str($query, $currentParameters); + } + + $queryString = http_build_query(array_merge($currentParameters, $this->getValues()), '', '&'); + + $pos = strpos($uri, '?'); + $base = false === $pos ? $uri : substr($uri, 0, $pos); + $uri = rtrim($base.'?'.$queryString, '?'); + } + + return $uri; + } + + protected function getRawUri() + { + // If the form was created from a button rather than the form node, check for HTML5 action overrides + if ($this->button !== $this->node && $this->button->getAttribute('formaction')) { + return $this->button->getAttribute('formaction'); + } + + return $this->node->getAttribute('action'); + } + + /** + * Gets the form method. + * + * If no method is defined in the form, GET is returned. + * + * @return string The method + */ + public function getMethod() + { + if (null !== $this->method) { + return $this->method; + } + + // If the form was created from a button rather than the form node, check for HTML5 method override + if ($this->button !== $this->node && $this->button->getAttribute('formmethod')) { + return strtoupper($this->button->getAttribute('formmethod')); + } + + return $this->node->getAttribute('method') ? strtoupper($this->node->getAttribute('method')) : 'GET'; + } + + /** + * Returns true if the named field exists. + * + * @param string $name The field name + * + * @return bool true if the field exists, false otherwise + */ + public function has($name) + { + return $this->fields->has($name); + } + + /** + * Removes a field from the form. + * + * @param string $name The field name + */ + public function remove($name) + { + $this->fields->remove($name); + } + + /** + * Gets a named field. + * + * @param string $name The field name + * + * @return FormField|FormField[]|FormField[][] The value of the field + * + * @throws \InvalidArgumentException When field is not present in this form + */ + public function get($name) + { + return $this->fields->get($name); + } + + /** + * Sets a named field. + */ + public function set(FormField $field) + { + $this->fields->add($field); + } + + /** + * Gets all fields. + * + * @return FormField[] + */ + public function all() + { + return $this->fields->all(); + } + + /** + * Returns true if the named field exists. + * + * @param string $name The field name + * + * @return bool true if the field exists, false otherwise + */ + public function offsetExists($name) + { + return $this->has($name); + } + + /** + * Gets the value of a field. + * + * @param string $name The field name + * + * @return FormField|FormField[]|FormField[][] The value of the field + * + * @throws \InvalidArgumentException if the field does not exist + */ + public function offsetGet($name) + { + return $this->fields->get($name); + } + + /** + * Sets the value of a field. + * + * @param string $name The field name + * @param string|array $value The value of the field + * + * @throws \InvalidArgumentException if the field does not exist + */ + public function offsetSet($name, $value) + { + $this->fields->set($name, $value); + } + + /** + * Removes a field from the form. + * + * @param string $name The field name + */ + public function offsetUnset($name) + { + $this->fields->remove($name); + } + + /** + * Disables validation. + * + * @return self + */ + public function disableValidation() + { + foreach ($this->fields->all() as $field) { + if ($field instanceof Field\ChoiceFormField) { + $field->disableValidation(); + } + } + + return $this; + } + + /** + * Sets the node for the form. + * + * Expects a 'submit' button \DOMElement and finds the corresponding form element, or the form element itself. + * + * @throws \LogicException If given node is not a button or input or does not have a form ancestor + */ + protected function setNode(\DOMElement $node) + { + $this->button = $node; + if ('button' === $node->nodeName || ('input' === $node->nodeName && \in_array(strtolower($node->getAttribute('type')), ['submit', 'button', 'image']))) { + if ($node->hasAttribute('form')) { + // if the node has the HTML5-compliant 'form' attribute, use it + $formId = $node->getAttribute('form'); + $form = $node->ownerDocument->getElementById($formId); + if (null === $form) { + throw new \LogicException(sprintf('The selected node has an invalid form attribute (%s).', $formId)); + } + $this->node = $form; + + return; + } + // we loop until we find a form ancestor + do { + if (null === $node = $node->parentNode) { + throw new \LogicException('The selected node does not have a form ancestor.'); + } + } while ('form' !== $node->nodeName); + } elseif ('form' !== $node->nodeName) { + throw new \LogicException(sprintf('Unable to submit on a "%s" tag.', $node->nodeName)); + } + + $this->node = $node; + } + + /** + * Adds form elements related to this form. + * + * Creates an internal copy of the submitted 'button' element and + * the form node or the entire document depending on whether we need + * to find non-descendant elements through HTML5 'form' attribute. + */ + private function initialize() + { + $this->fields = new FormFieldRegistry(); + + $xpath = new \DOMXPath($this->node->ownerDocument); + + // add submitted button if it has a valid name + if ('form' !== $this->button->nodeName && $this->button->hasAttribute('name') && $this->button->getAttribute('name')) { + if ('input' == $this->button->nodeName && 'image' == strtolower($this->button->getAttribute('type'))) { + $name = $this->button->getAttribute('name'); + $this->button->setAttribute('value', '0'); + + // temporarily change the name of the input node for the x coordinate + $this->button->setAttribute('name', $name.'.x'); + $this->set(new Field\InputFormField($this->button)); + + // temporarily change the name of the input node for the y coordinate + $this->button->setAttribute('name', $name.'.y'); + $this->set(new Field\InputFormField($this->button)); + + // restore the original name of the input node + $this->button->setAttribute('name', $name); + } else { + $this->set(new Field\InputFormField($this->button)); + } + } + + // find form elements corresponding to the current form + if ($this->node->hasAttribute('id')) { + // corresponding elements are either descendants or have a matching HTML5 form attribute + $formId = Crawler::xpathLiteral($this->node->getAttribute('id')); + + $fieldNodes = $xpath->query(sprintf('( descendant::input[@form=%s] | descendant::button[@form=%1$s] | descendant::textarea[@form=%1$s] | descendant::select[@form=%1$s] | //form[@id=%1$s]//input[not(@form)] | //form[@id=%1$s]//button[not(@form)] | //form[@id=%1$s]//textarea[not(@form)] | //form[@id=%1$s]//select[not(@form)] )[not(ancestor::template)]', $formId)); + foreach ($fieldNodes as $node) { + $this->addField($node); + } + } else { + // do the xpath query with $this->node as the context node, to only find descendant elements + // however, descendant elements with form attribute are not part of this form + $fieldNodes = $xpath->query('( descendant::input[not(@form)] | descendant::button[not(@form)] | descendant::textarea[not(@form)] | descendant::select[not(@form)] )[not(ancestor::template)]', $this->node); + foreach ($fieldNodes as $node) { + $this->addField($node); + } + } + + if ($this->baseHref && '' !== $this->node->getAttribute('action')) { + $this->currentUri = $this->baseHref; + } + } + + private function addField(\DOMElement $node) + { + if (!$node->hasAttribute('name') || !$node->getAttribute('name')) { + return; + } + + $nodeName = $node->nodeName; + if ('select' == $nodeName || 'input' == $nodeName && 'checkbox' == strtolower($node->getAttribute('type'))) { + $this->set(new Field\ChoiceFormField($node)); + } elseif ('input' == $nodeName && 'radio' == strtolower($node->getAttribute('type'))) { + // there may be other fields with the same name that are no choice + // fields already registered (see https://github.com/symfony/symfony/issues/11689) + if ($this->has($node->getAttribute('name')) && $this->get($node->getAttribute('name')) instanceof ChoiceFormField) { + $this->get($node->getAttribute('name'))->addChoice($node); + } else { + $this->set(new Field\ChoiceFormField($node)); + } + } elseif ('input' == $nodeName && 'file' == strtolower($node->getAttribute('type'))) { + $this->set(new Field\FileFormField($node)); + } elseif ('input' == $nodeName && !\in_array(strtolower($node->getAttribute('type')), ['submit', 'button', 'image'])) { + $this->set(new Field\InputFormField($node)); + } elseif ('textarea' == $nodeName) { + $this->set(new Field\TextareaFormField($node)); + } + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/FormFieldRegistry.php b/www/multitube/vendor/symfony/dom-crawler/FormFieldRegistry.php new file mode 100644 index 0000000..af8bcfb --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/FormFieldRegistry.php @@ -0,0 +1,195 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +use Symfony\Component\DomCrawler\Field\FormField; + +/** + * This is an internal class that must not be used directly. + * + * @internal + */ +class FormFieldRegistry +{ + private $fields = []; + + private $base; + + /** + * Adds a field to the registry. + */ + public function add(FormField $field) + { + $segments = $this->getSegments($field->getName()); + + $target = &$this->fields; + while ($segments) { + if (!\is_array($target)) { + $target = []; + } + $path = array_shift($segments); + if ('' === $path) { + $target = &$target[]; + } else { + $target = &$target[$path]; + } + } + $target = $field; + } + + /** + * Removes a field and its children from the registry. + * + * @param string $name The fully qualified name of the base field + */ + public function remove($name) + { + $segments = $this->getSegments($name); + $target = &$this->fields; + while (\count($segments) > 1) { + $path = array_shift($segments); + if (!\is_array($target) || !\array_key_exists($path, $target)) { + return; + } + $target = &$target[$path]; + } + unset($target[array_shift($segments)]); + } + + /** + * Returns the value of the field and its children. + * + * @param string $name The fully qualified name of the field + * + * @return FormField|FormField[]|FormField[][] The value of the field + * + * @throws \InvalidArgumentException if the field does not exist + */ + public function &get($name) + { + $segments = $this->getSegments($name); + $target = &$this->fields; + while ($segments) { + $path = array_shift($segments); + if (!\is_array($target) || !\array_key_exists($path, $target)) { + throw new \InvalidArgumentException(sprintf('Unreachable field "%s".', $path)); + } + $target = &$target[$path]; + } + + return $target; + } + + /** + * Tests whether the form has the given field. + * + * @param string $name The fully qualified name of the field + * + * @return bool Whether the form has the given field + */ + public function has($name) + { + try { + $this->get($name); + + return true; + } catch (\InvalidArgumentException $e) { + return false; + } + } + + /** + * Set the value of a field and its children. + * + * @param string $name The fully qualified name of the field + * @param mixed $value The value + * + * @throws \InvalidArgumentException if the field does not exist + */ + public function set($name, $value) + { + $target = &$this->get($name); + if ((!\is_array($value) && $target instanceof Field\FormField) || $target instanceof Field\ChoiceFormField) { + $target->setValue($value); + } elseif (\is_array($value)) { + $registry = new static(); + $registry->base = $name; + $registry->fields = $value; + foreach ($registry->all() as $k => $v) { + $this->set($k, $v); + } + } else { + throw new \InvalidArgumentException(sprintf('Cannot set value on a compound field "%s".', $name)); + } + } + + /** + * Returns the list of field with their value. + * + * @return FormField[] The list of fields as [string] Fully qualified name => (mixed) value) + */ + public function all() + { + return $this->walk($this->fields, $this->base); + } + + /** + * Transforms a PHP array in a list of fully qualified name / value. + * + * @param array $array The PHP array + * @param string $base The name of the base field + * @param array $output The initial values + * + * @return array The list of fields as [string] Fully qualified name => (mixed) value) + */ + private function walk(array $array, $base = '', array &$output = []) + { + foreach ($array as $k => $v) { + $path = empty($base) ? $k : sprintf('%s[%s]', $base, $k); + if (\is_array($v)) { + $this->walk($v, $path, $output); + } else { + $output[$path] = $v; + } + } + + return $output; + } + + /** + * Splits a field name into segments as a web browser would do. + * + * getSegments('base[foo][3][]') = ['base', 'foo, '3', '']; + * + * @param string $name The name of the field + * + * @return string[] The list of segments + */ + private function getSegments($name) + { + if (preg_match('/^(?P[^[]+)(?P(\[.*)|$)/', $name, $m)) { + $segments = [$m['base']]; + while (!empty($m['extra'])) { + $extra = $m['extra']; + if (preg_match('/^\[(?P.*?)\](?P.*)$/', $extra, $m)) { + $segments[] = $m['segment']; + } else { + $segments[] = $extra; + } + } + + return $segments; + } + + return [$name]; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/Image.php b/www/multitube/vendor/symfony/dom-crawler/Image.php new file mode 100644 index 0000000..4d64032 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Image.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +/** + * Image represents an HTML image (an HTML img tag). + */ +class Image extends AbstractUriElement +{ + public function __construct(\DOMElement $node, $currentUri) + { + parent::__construct($node, $currentUri, 'GET'); + } + + protected function getRawUri() + { + return $this->node->getAttribute('src'); + } + + protected function setNode(\DOMElement $node) + { + if ('img' !== $node->nodeName) { + throw new \LogicException(sprintf('Unable to visualize a "%s" tag.', $node->nodeName)); + } + + $this->node = $node; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/LICENSE b/www/multitube/vendor/symfony/dom-crawler/LICENSE new file mode 100644 index 0000000..9e936ec --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2004-2020 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/www/multitube/vendor/symfony/dom-crawler/Link.php b/www/multitube/vendor/symfony/dom-crawler/Link.php new file mode 100644 index 0000000..80a356e --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Link.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler; + +/** + * Link represents an HTML link (an HTML a, area or link tag). + * + * @author Fabien Potencier + */ +class Link extends AbstractUriElement +{ + protected function getRawUri() + { + return $this->node->getAttribute('href'); + } + + protected function setNode(\DOMElement $node) + { + if ('a' !== $node->nodeName && 'area' !== $node->nodeName && 'link' !== $node->nodeName) { + throw new \LogicException(sprintf('Unable to navigate from a "%s" tag.', $node->nodeName)); + } + + $this->node = $node; + } +} diff --git a/www/multitube/vendor/symfony/dom-crawler/README.md b/www/multitube/vendor/symfony/dom-crawler/README.md new file mode 100644 index 0000000..5fad2e2 --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/README.md @@ -0,0 +1,13 @@ +DomCrawler Component +==================== + +The DomCrawler component eases DOM navigation for HTML and XML documents. + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/dom_crawler.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/www/multitube/vendor/symfony/dom-crawler/Tests/CrawlerTest.php b/www/multitube/vendor/symfony/dom-crawler/Tests/CrawlerTest.php new file mode 100644 index 0000000..26164dc --- /dev/null +++ b/www/multitube/vendor/symfony/dom-crawler/Tests/CrawlerTest.php @@ -0,0 +1,1193 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DomCrawler\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DomCrawler\Crawler; + +class CrawlerTest extends TestCase +{ + public function testConstructor() + { + $crawler = new Crawler(); + $this->assertCount(0, $crawler, '__construct() returns an empty crawler'); + + $doc = new \DOMDocument(); + $node = $doc->createElement('test'); + + $crawler = new Crawler($node); + $this->assertCount(1, $crawler, '__construct() takes a node as a first argument'); + } + + public function testGetUri() + { + $uri = 'http://symfony.com'; + $crawler = new Crawler(null, $uri); + $this->assertEquals($uri, $crawler->getUri()); + } + + public function testGetBaseHref() + { + $baseHref = 'http://symfony.com'; + $crawler = new Crawler(null, null, $baseHref); + $this->assertEquals($baseHref, $crawler->getBaseHref()); + } + + public function testAdd() + { + $crawler = new Crawler(); + $crawler->add($this->createDomDocument()); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMDocument'); + + $crawler = new Crawler(); + $crawler->add($this->createNodeList()); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNodeList'); + + $list = []; + foreach ($this->createNodeList() as $node) { + $list[] = $node; + } + $crawler = new Crawler(); + $crawler->add($list); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from an array of nodes'); + + $crawler = new Crawler(); + $crawler->add($this->createNodeList()->item(0)); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->add() adds nodes from a \DOMNode'); + + $crawler = new Crawler(); + $crawler->add('Foo'); + $this->assertEquals('Foo', $crawler->filterXPath('//body')->text(), '->add() adds nodes from a string'); + } + + public function testAddInvalidType() + { + $this->expectException('InvalidArgumentException'); + $crawler = new Crawler(); + $crawler->add(1); + } + + public function testAddMultipleDocumentNode() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Attaching DOM nodes from multiple documents in the same crawler is forbidden.'); + $crawler = $this->createTestCrawler(); + $crawler->addHtmlContent('
', 'UTF-8'); + } + + public function testAddHtmlContent() + { + $crawler = new Crawler(); + $crawler->addHtmlContent('
', 'UTF-8'); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addHtmlContent() adds nodes from an HTML string'); + } + + public function testAddHtmlContentWithBaseTag() + { + $crawler = new Crawler(); + + $crawler->addHtmlContent('', 'UTF-8'); + + $this->assertEquals('http://symfony.com', $crawler->filterXPath('//base')->attr('href'), '->addHtmlContent() adds nodes from an HTML string'); + $this->assertEquals('http://symfony.com/contact', $crawler->filterXPath('//a')->link()->getUri(), '->addHtmlContent() adds nodes from an HTML string'); + } + + /** + * @requires extension mbstring + */ + public function testAddHtmlContentCharset() + { + $crawler = new Crawler(); + $crawler->addHtmlContent('
Tiếng Việt', 'UTF-8'); + + $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text()); + } + + public function testAddHtmlContentInvalidBaseTag() + { + $crawler = new Crawler(null, 'http://symfony.com'); + + $crawler->addHtmlContent('', 'UTF-8'); + + $this->assertEquals('http://symfony.com/contact', current($crawler->filterXPath('//a')->links())->getUri(), '->addHtmlContent() correctly handles a non-existent base tag href attribute'); + } + + public function testAddHtmlContentUnsupportedCharset() + { + $crawler = new Crawler(); + $crawler->addHtmlContent(file_get_contents(__DIR__.'/Fixtures/windows-1250.html'), 'Windows-1250'); + + $this->assertEquals('Žťčýů', $crawler->filterXPath('//p')->text()); + } + + /** + * @requires extension mbstring + */ + public function testAddHtmlContentCharsetGbk() + { + $crawler = new Crawler(); + //gbk encode of

中文

+ $crawler->addHtmlContent(base64_decode('PGh0bWw+PHA+1tDOxDwvcD48L2h0bWw+'), 'gbk'); + + $this->assertEquals('中文', $crawler->filterXPath('//p')->text()); + } + + public function testAddHtmlContentWithErrors() + { + $internalErrors = libxml_use_internal_errors(true); + + $crawler = new Crawler(); + $crawler->addHtmlContent(<<<'EOF' + + + + + + + + +EOF + , 'UTF-8'); + + $errors = libxml_get_errors(); + $this->assertCount(1, $errors); + $this->assertEquals("Tag nav invalid\n", $errors[0]->message); + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + } + + public function testAddXmlContent() + { + $crawler = new Crawler(); + $crawler->addXmlContent('
', 'UTF-8'); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addXmlContent() adds nodes from an XML string'); + } + + public function testAddXmlContentCharset() + { + $crawler = new Crawler(); + $crawler->addXmlContent('
Tiếng Việt
', 'UTF-8'); + + $this->assertEquals('Tiếng Việt', $crawler->filterXPath('//div')->text()); + } + + public function testAddXmlContentWithErrors() + { + $internalErrors = libxml_use_internal_errors(true); + + $crawler = new Crawler(); + $crawler->addXmlContent(<<<'EOF' + + + + + +
+ + +EOF + , 'UTF-8'); + + $this->assertGreaterThan(1, libxml_get_errors()); + + libxml_clear_errors(); + libxml_use_internal_errors($internalErrors); + } + + public function testAddContent() + { + $crawler = new Crawler(); + $crawler->addContent('
', 'text/html; charset=UTF-8'); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string'); + + $crawler = new Crawler(); + $crawler->addContent('
', 'text/html; charset=UTF-8; dir=RTL'); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an HTML string with extended content type'); + + $crawler = new Crawler(); + $crawler->addContent('
'); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() uses text/html as the default type'); + + $crawler = new Crawler(); + $crawler->addContent('
', 'text/xml; charset=UTF-8'); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string'); + + $crawler = new Crawler(); + $crawler->addContent('
', 'text/xml'); + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addContent() adds nodes from an XML string'); + + $crawler = new Crawler(); + $crawler->addContent('foo bar', 'text/plain'); + $this->assertCount(0, $crawler, '->addContent() does nothing if the type is not (x|ht)ml'); + + $crawler = new Crawler(); + $crawler->addContent('中文'); + $this->assertEquals('中文', $crawler->filterXPath('//span')->text(), '->addContent() guess wrong charset'); + } + + /** + * @requires extension iconv + */ + public function testAddContentNonUtf8() + { + $crawler = new Crawler(); + $crawler->addContent(iconv('UTF-8', 'SJIS', '日本語')); + $this->assertEquals('日本語', $crawler->filterXPath('//body')->text(), '->addContent() can recognize "Shift_JIS" in html5 meta charset tag'); + } + + public function testAddDocument() + { + $crawler = new Crawler(); + $crawler->addDocument($this->createDomDocument()); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addDocument() adds nodes from a \DOMDocument'); + } + + public function testAddNodeList() + { + $crawler = new Crawler(); + $crawler->addNodeList($this->createNodeList()); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodeList() adds nodes from a \DOMNodeList'); + } + + public function testAddNodes() + { + $list = []; + foreach ($this->createNodeList() as $node) { + $list[] = $node; + } + + $crawler = new Crawler(); + $crawler->addNodes($list); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNodes() adds nodes from an array of nodes'); + } + + public function testAddNode() + { + $crawler = new Crawler(); + $crawler->addNode($this->createNodeList()->item(0)); + + $this->assertEquals('foo', $crawler->filterXPath('//div')->attr('class'), '->addNode() adds nodes from a \DOMNode'); + } + + public function testClear() + { + $doc = new \DOMDocument(); + $node = $doc->createElement('test'); + + $crawler = new Crawler($node); + $crawler->clear(); + $this->assertCount(0, $crawler, '->clear() removes all the nodes from the crawler'); + } + + public function testEq() + { + $crawler = $this->createTestCrawler()->filterXPath('//li'); + $this->assertNotSame($crawler, $crawler->eq(0), '->eq() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->eq() returns a new instance of a crawler'); + + $this->assertEquals('Two', $crawler->eq(1)->text(), '->eq() returns the nth node of the list'); + $this->assertCount(0, $crawler->eq(100), '->eq() returns an empty crawler if the nth node does not exist'); + } + + public function testEach() + { + $data = $this->createTestCrawler()->filterXPath('//ul[1]/li')->each(function ($node, $i) { + return $i.'-'.$node->text(); + }); + + $this->assertEquals(['0-One', '1-Two', '2-Three'], $data, '->each() executes an anonymous function on each node of the list'); + } + + public function testIteration() + { + $crawler = $this->createTestCrawler()->filterXPath('//li'); + + $this->assertInstanceOf('Traversable', $crawler); + $this->assertContainsOnlyInstancesOf('DOMElement', iterator_to_array($crawler), 'Iterating a Crawler gives DOMElement instances'); + } + + public function testSlice() + { + $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); + $this->assertNotSame($crawler->slice(), $crawler, '->slice() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler->slice(), '->slice() returns a new instance of a crawler'); + + $this->assertCount(3, $crawler->slice(), '->slice() does not slice the nodes in the list if any param is entered'); + $this->assertCount(1, $crawler->slice(1, 1), '->slice() slices the nodes in the list'); + } + + public function testReduce() + { + $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); + $nodes = $crawler->reduce(function ($node, $i) { + return 1 !== $i; + }); + $this->assertNotSame($nodes, $crawler, '->reduce() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $nodes, '->reduce() returns a new instance of a crawler'); + + $this->assertCount(2, $nodes, '->reduce() filters the nodes in the list'); + } + + public function testAttr() + { + $this->assertEquals('first', $this->createTestCrawler()->filterXPath('//li')->attr('class'), '->attr() returns the attribute of the first element of the node list'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->attr('class'); + $this->fail('->attr() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->attr() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testMissingAttrValueIsNull() + { + $crawler = new Crawler(); + $crawler->addContent('
', 'text/html; charset=UTF-8'); + $div = $crawler->filterXPath('//div'); + + $this->assertEquals('sample value', $div->attr('non-empty-attr'), '->attr() reads non-empty attributes correctly'); + $this->assertEquals('', $div->attr('empty-attr'), '->attr() reads empty attributes correctly'); + $this->assertNull($div->attr('missing-attr'), '->attr() reads missing attributes correctly'); + } + + public function testNodeName() + { + $this->assertEquals('li', $this->createTestCrawler()->filterXPath('//li')->nodeName(), '->nodeName() returns the node name of the first element of the node list'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->nodeName(); + $this->fail('->nodeName() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->nodeName() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testText() + { + $this->assertEquals('One', $this->createTestCrawler()->filterXPath('//li')->text(), '->text() returns the node value of the first element of the node list'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->text(); + $this->fail('->text() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->text() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testHtml() + { + $this->assertEquals('Bar', $this->createTestCrawler()->filterXPath('//a[5]')->html()); + $this->assertEquals('', trim(preg_replace('~>\s+<~', '><', $this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html()))); + + try { + $this->createTestCrawler()->filterXPath('//ol')->html(); + $this->fail('->html() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->html() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testExtract() + { + $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); + + $this->assertEquals(['One', 'Two', 'Three'], $crawler->extract('_text'), '->extract() returns an array of extracted data from the node list'); + $this->assertEquals([['One', 'first'], ['Two', ''], ['Three', '']], $crawler->extract(['_text', 'class']), '->extract() returns an array of extracted data from the node list'); + $this->assertEquals([[], [], []], $crawler->extract([]), '->extract() returns empty arrays if the attribute list is empty'); + + $this->assertEquals([], $this->createTestCrawler()->filterXPath('//ol')->extract('_text'), '->extract() returns an empty array if the node list is empty'); + } + + public function testFilterXpathComplexQueries() + { + $crawler = $this->createTestCrawler()->filterXPath('//body'); + + $this->assertCount(0, $crawler->filterXPath('/input')); + $this->assertCount(0, $crawler->filterXPath('/body')); + $this->assertCount(1, $crawler->filterXPath('./body')); + $this->assertCount(1, $crawler->filterXPath('.//body')); + $this->assertCount(5, $crawler->filterXPath('.//input')); + $this->assertCount(4, $crawler->filterXPath('//form')->filterXPath('//button | //input')); + $this->assertCount(1, $crawler->filterXPath('body')); + $this->assertCount(6, $crawler->filterXPath('//button | //input')); + $this->assertCount(1, $crawler->filterXPath('//body')); + $this->assertCount(1, $crawler->filterXPath('descendant-or-self::body')); + $this->assertCount(1, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('./div'), 'A child selection finds only the current div'); + $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('descendant::div'), 'A descendant selector matches the current div and its child'); + $this->assertCount(3, $crawler->filterXPath('//div[@id="parent"]')->filterXPath('//div'), 'A descendant selector matches the current div and its child'); + $this->assertCount(5, $crawler->filterXPath('(//a | //div)//img')); + $this->assertCount(7, $crawler->filterXPath('((//a | //div)//img | //ul)')); + $this->assertCount(7, $crawler->filterXPath('( ( //a | //div )//img | //ul )')); + $this->assertCount(1, $crawler->filterXPath("//a[./@href][((./@id = 'Klausi|Claudiu' or normalize-space(string(.)) = 'Klausi|Claudiu' or ./@title = 'Klausi|Claudiu' or ./@rel = 'Klausi|Claudiu') or .//img[./@alt = 'Klausi|Claudiu'])]")); + } + + public function testFilterXPath() + { + $crawler = $this->createTestCrawler(); + $this->assertNotSame($crawler, $crawler->filterXPath('//li'), '->filterXPath() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filterXPath() returns a new instance of a crawler'); + + $crawler = $this->createTestCrawler()->filterXPath('//ul'); + $this->assertCount(6, $crawler->filterXPath('//li'), '->filterXPath() filters the node list with the XPath expression'); + + $crawler = $this->createTestCrawler(); + $this->assertCount(3, $crawler->filterXPath('//body')->filterXPath('//button')->parents(), '->filterXpath() preserves parents when chained'); + } + + public function testFilterRemovesDuplicates() + { + $crawler = $this->createTestCrawler()->filter('html, body')->filter('li'); + $this->assertCount(6, $crawler, 'The crawler removes duplicates when filtering.'); + } + + public function testFilterXPathWithDefaultNamespace() + { + $crawler = $this->createTestXmlCrawler()->filterXPath('//default:entry/default:id'); + $this->assertCount(1, $crawler, '->filterXPath() automatically registers a namespace'); + $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); + } + + public function testFilterXPathWithCustomDefaultNamespace() + { + $crawler = $this->createTestXmlCrawler(); + $crawler->setDefaultNamespacePrefix('x'); + $crawler = $crawler->filterXPath('//x:entry/x:id'); + + $this->assertCount(1, $crawler, '->filterXPath() lets to override the default namespace prefix'); + $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); + } + + public function testFilterXPathWithNamespace() + { + $crawler = $this->createTestXmlCrawler()->filterXPath('//yt:accessControl'); + $this->assertCount(2, $crawler, '->filterXPath() automatically registers a namespace'); + } + + public function testFilterXPathWithMultipleNamespaces() + { + $crawler = $this->createTestXmlCrawler()->filterXPath('//media:group/yt:aspectRatio'); + $this->assertCount(1, $crawler, '->filterXPath() automatically registers multiple namespaces'); + $this->assertSame('widescreen', $crawler->text()); + } + + public function testFilterXPathWithManuallyRegisteredNamespace() + { + $crawler = $this->createTestXmlCrawler(); + $crawler->registerNamespace('m', 'http://search.yahoo.com/mrss/'); + + $crawler = $crawler->filterXPath('//m:group/yt:aspectRatio'); + $this->assertCount(1, $crawler, '->filterXPath() uses manually registered namespace'); + $this->assertSame('widescreen', $crawler->text()); + } + + public function testFilterXPathWithAnUrl() + { + $crawler = $this->createTestXmlCrawler(); + + $crawler = $crawler->filterXPath('//media:category[@scheme="http://gdata.youtube.com/schemas/2007/categories.cat"]'); + $this->assertCount(1, $crawler); + $this->assertSame('Music', $crawler->text()); + } + + public function testFilterXPathWithFakeRoot() + { + $crawler = $this->createTestCrawler(); + $this->assertCount(0, $crawler->filterXPath('.'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + $this->assertCount(0, $crawler->filterXPath('self::*'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + $this->assertCount(0, $crawler->filterXPath('self::_root'), '->filterXPath() returns an empty result if the XPath references the fake root node'); + } + + public function testFilterXPathWithAncestorAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//form'); + + $this->assertCount(0, $crawler->filterXPath('ancestor::*'), 'The fake root node has no ancestor nodes'); + } + + public function testFilterXPathWithAncestorOrSelfAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//form'); + + $this->assertCount(0, $crawler->filterXPath('ancestor-or-self::*'), 'The fake root node has no ancestor nodes'); + } + + public function testFilterXPathWithAttributeAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//form'); + + $this->assertCount(0, $crawler->filterXPath('attribute::*'), 'The fake root node has no attribute nodes'); + } + + public function testFilterXPathWithAttributeAxisAfterElementAxis() + { + $this->assertCount(3, $this->createTestCrawler()->filterXPath('//form/button/attribute::*'), '->filterXPath() handles attribute axes properly when they are preceded by an element filtering axis'); + } + + public function testFilterXPathWithChildAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]'); + + $this->assertCount(1, $crawler->filterXPath('child::div'), 'A child selection finds only the current div'); + } + + public function testFilterXPathWithFollowingAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//a'); + + $this->assertCount(0, $crawler->filterXPath('following::div'), 'The fake root node has no following nodes'); + } + + public function testFilterXPathWithFollowingSiblingAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//a'); + + $this->assertCount(0, $crawler->filterXPath('following-sibling::div'), 'The fake root node has no following nodes'); + } + + public function testFilterXPathWithNamespaceAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//button'); + + $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'The fake root node has no namespace nodes'); + } + + public function testFilterXPathWithNamespaceAxisAfterElementAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//div[@id="parent"]/namespace::*'); + + $this->assertCount(0, $crawler->filterXPath('namespace::*'), 'Namespace axes cannot be requested'); + } + + public function testFilterXPathWithParentAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//button'); + + $this->assertCount(0, $crawler->filterXPath('parent::*'), 'The fake root node has no parent nodes'); + } + + public function testFilterXPathWithPrecedingAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//form'); + + $this->assertCount(0, $crawler->filterXPath('preceding::*'), 'The fake root node has no preceding nodes'); + } + + public function testFilterXPathWithPrecedingSiblingAxis() + { + $crawler = $this->createTestCrawler()->filterXPath('//form'); + + $this->assertCount(0, $crawler->filterXPath('preceding-sibling::*'), 'The fake root node has no preceding nodes'); + } + + public function testFilterXPathWithSelfAxes() + { + $crawler = $this->createTestCrawler()->filterXPath('//a'); + + $this->assertCount(0, $crawler->filterXPath('self::a'), 'The fake root node has no "real" element name'); + $this->assertCount(0, $crawler->filterXPath('self::a/img'), 'The fake root node has no "real" element name'); + $this->assertCount(10, $crawler->filterXPath('self::*/a')); + } + + public function testFilter() + { + $crawler = $this->createTestCrawler(); + $this->assertNotSame($crawler, $crawler->filter('li'), '->filter() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->filter() returns a new instance of a crawler'); + + $crawler = $this->createTestCrawler()->filter('ul'); + + $this->assertCount(6, $crawler->filter('li'), '->filter() filters the node list with the CSS selector'); + } + + public function testFilterWithDefaultNamespace() + { + $crawler = $this->createTestXmlCrawler()->filter('default|entry default|id'); + $this->assertCount(1, $crawler, '->filter() automatically registers namespaces'); + $this->assertSame('tag:youtube.com,2008:video:kgZRZmEc9j4', $crawler->text()); + } + + public function testFilterWithNamespace() + { + $crawler = $this->createTestXmlCrawler()->filter('yt|accessControl'); + $this->assertCount(2, $crawler, '->filter() automatically registers namespaces'); + } + + public function testFilterWithMultipleNamespaces() + { + $crawler = $this->createTestXmlCrawler()->filter('media|group yt|aspectRatio'); + $this->assertCount(1, $crawler, '->filter() automatically registers namespaces'); + $this->assertSame('widescreen', $crawler->text()); + } + + public function testFilterWithDefaultNamespaceOnly() + { + $crawler = new Crawler(' + + + http://localhost/foo + weekly + 0.5 + 2012-11-16 + + + http://localhost/bar + weekly + 0.5 + 2012-11-16 + + + '); + + $this->assertEquals(2, $crawler->filter('url')->count()); + } + + public function testSelectLink() + { + $crawler = $this->createTestCrawler(); + $this->assertNotSame($crawler, $crawler->selectLink('Foo'), '->selectLink() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectLink() returns a new instance of a crawler'); + + $this->assertCount(1, $crawler->selectLink('Fabien\'s Foo'), '->selectLink() selects links by the node values'); + $this->assertCount(1, $crawler->selectLink('Fabien\'s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); + + $this->assertCount(2, $crawler->selectLink('Fabien"s Foo'), '->selectLink() selects links by the node values'); + $this->assertCount(2, $crawler->selectLink('Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); + + $this->assertCount(1, $crawler->selectLink('\' Fabien"s Foo'), '->selectLink() selects links by the node values'); + $this->assertCount(1, $crawler->selectLink('\' Fabien"s Bar'), '->selectLink() selects links by the alt attribute of a clickable image'); + + $this->assertCount(4, $crawler->selectLink('Foo'), '->selectLink() selects links by the node values'); + $this->assertCount(4, $crawler->selectLink('Bar'), '->selectLink() selects links by the node values'); + } + + public function testSelectImage() + { + $crawler = $this->createTestCrawler(); + $this->assertNotSame($crawler, $crawler->selectImage('Bar'), '->selectImage() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectImage() returns a new instance of a crawler'); + + $this->assertCount(1, $crawler->selectImage('Fabien\'s Bar'), '->selectImage() selects images by alt attribute'); + $this->assertCount(2, $crawler->selectImage('Fabien"s Bar'), '->selectImage() selects images by alt attribute'); + $this->assertCount(1, $crawler->selectImage('\' Fabien"s Bar'), '->selectImage() selects images by alt attribute'); + } + + public function testSelectButton() + { + $crawler = $this->createTestCrawler(); + $this->assertNotSame($crawler, $crawler->selectButton('FooValue'), '->selectButton() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->selectButton() returns a new instance of a crawler'); + + $this->assertEquals(1, $crawler->selectButton('FooValue')->count(), '->selectButton() selects buttons'); + $this->assertEquals(1, $crawler->selectButton('FooName')->count(), '->selectButton() selects buttons'); + $this->assertEquals(1, $crawler->selectButton('FooId')->count(), '->selectButton() selects buttons'); + + $this->assertEquals(1, $crawler->selectButton('BarValue')->count(), '->selectButton() selects buttons'); + $this->assertEquals(1, $crawler->selectButton('BarName')->count(), '->selectButton() selects buttons'); + $this->assertEquals(1, $crawler->selectButton('BarId')->count(), '->selectButton() selects buttons'); + + $this->assertEquals(1, $crawler->selectButton('FooBarValue')->count(), '->selectButton() selects buttons with form attribute too'); + $this->assertEquals(1, $crawler->selectButton('FooBarName')->count(), '->selectButton() selects buttons with form attribute too'); + } + + public function testSelectButtonWithSingleQuotesInNameAttribute() + { + $html = <<<'HTML' + + + +
+
+ +
+ + +HTML; + + $crawler = new Crawler($html); + + $this->assertCount(1, $crawler->selectButton('Click \'Here\'')); + } + + public function testSelectButtonWithDoubleQuotesInNameAttribute() + { + $html = <<<'HTML' + + + +
+ Login +
+
+ +
+ + +HTML; + + $crawler = new Crawler($html); + + $this->assertCount(1, $crawler->selectButton('Click "Here"')); + } + + public function testLink() + { + $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $crawler->link(), '->link() returns a Link instance'); + + $this->assertEquals('POST', $crawler->link('post')->getMethod(), '->link() takes a method as its argument'); + + $crawler = $this->createTestCrawler('http://example.com/bar')->selectLink('GetLink'); + $this->assertEquals('http://example.com/bar?get=param', $crawler->link()->getUri(), '->link() returns a Link instance'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->link(); + $this->fail('->link() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->link() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testInvalidLink() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The selected node should be instance of DOMElement'); + $crawler = $this->createTestCrawler('http://example.com/bar/'); + $crawler->filterXPath('//li/text()')->link(); + } + + public function testInvalidLinks() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The selected node should be instance of DOMElement'); + $crawler = $this->createTestCrawler('http://example.com/bar/'); + $crawler->filterXPath('//li/text()')->link(); + } + + public function testImage() + { + $crawler = $this->createTestCrawler('http://example.com/bar/')->selectImage('Bar'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Image', $crawler->image(), '->image() returns an Image instance'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->image(); + $this->fail('->image() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->image() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testSelectLinkAndLinkFiltered() + { + $html = <<<'HTML' + + + +
+ Login +
+
+ +
+ + +HTML; + + $crawler = new Crawler($html); + $filtered = $crawler->filterXPath("descendant-or-self::*[@id = 'login-form']"); + + $this->assertCount(0, $filtered->selectLink('Login')); + $this->assertCount(1, $filtered->selectButton('Submit')); + + $filtered = $crawler->filterXPath("descendant-or-self::*[@id = 'action']"); + + $this->assertCount(1, $filtered->selectLink('Login')); + $this->assertCount(0, $filtered->selectButton('Submit')); + + $this->assertCount(1, $crawler->selectLink('Login')->selectLink('Login')); + $this->assertCount(1, $crawler->selectButton('Submit')->selectButton('Submit')); + } + + public function testChaining() + { + $crawler = new Crawler('
'); + + $this->assertEquals('a', $crawler->filterXPath('//div')->filterXPath('div')->filterXPath('div')->attr('name')); + } + + public function testLinks() + { + $crawler = $this->createTestCrawler('http://example.com/bar/')->selectLink('Foo'); + $this->assertIsArray($crawler->links(), '->links() returns an array'); + + $this->assertCount(4, $crawler->links(), '->links() returns an array'); + $links = $crawler->links(); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Link', $links[0], '->links() returns an array of Link instances'); + + $this->assertEquals([], $this->createTestCrawler()->filterXPath('//ol')->links(), '->links() returns an empty array if the node selection is empty'); + } + + public function testImages() + { + $crawler = $this->createTestCrawler('http://example.com/bar/')->selectImage('Bar'); + $this->assertIsArray($crawler->images(), '->images() returns an array'); + + $this->assertCount(4, $crawler->images(), '->images() returns an array'); + $images = $crawler->images(); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Image', $images[0], '->images() returns an array of Image instances'); + + $this->assertEquals([], $this->createTestCrawler()->filterXPath('//ol')->links(), '->links() returns an empty array if the node selection is empty'); + } + + public function testForm() + { + $testCrawler = $this->createTestCrawler('http://example.com/bar/'); + $crawler = $testCrawler->selectButton('FooValue'); + $crawler2 = $testCrawler->selectButton('FooBarValue'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler->form(), '->form() returns a Form instance'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Form', $crawler2->form(), '->form() returns a Form instance'); + + $this->assertEquals($crawler->form()->getFormNode()->getAttribute('id'), $crawler2->form()->getFormNode()->getAttribute('id'), '->form() works on elements with form attribute'); + + $this->assertEquals(['FooName' => 'FooBar', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'], $crawler->form(['FooName' => 'FooBar'])->getValues(), '->form() takes an array of values to submit as its first argument'); + $this->assertEquals(['FooName' => 'FooValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'], $crawler->form()->getValues(), '->getValues() returns correct form values'); + $this->assertEquals(['FooBarName' => 'FooBarValue', 'TextName' => 'TextValue', 'FooTextName' => 'FooTextValue'], $crawler2->form()->getValues(), '->getValues() returns correct form values'); + + try { + $this->createTestCrawler()->filterXPath('//ol')->form(); + $this->fail('->form() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->form() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testInvalidForm() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The selected node should be instance of DOMElement'); + $crawler = $this->createTestCrawler('http://example.com/bar/'); + $crawler->filterXPath('//li/text()')->form(); + } + + public function testLast() + { + $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); + $this->assertNotSame($crawler, $crawler->last(), '->last() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->last() returns a new instance of a crawler'); + + $this->assertEquals('Three', $crawler->last()->text()); + } + + public function testFirst() + { + $crawler = $this->createTestCrawler()->filterXPath('//li'); + $this->assertNotSame($crawler, $crawler->first(), '->first() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->first() returns a new instance of a crawler'); + + $this->assertEquals('One', $crawler->first()->text()); + } + + public function testSiblings() + { + $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1); + $this->assertNotSame($crawler, $crawler->siblings(), '->siblings() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->siblings() returns a new instance of a crawler'); + + $nodes = $crawler->siblings(); + $this->assertEquals(2, $nodes->count()); + $this->assertEquals('One', $nodes->eq(0)->text()); + $this->assertEquals('Three', $nodes->eq(1)->text()); + + $nodes = $this->createTestCrawler()->filterXPath('//li')->eq(0)->siblings(); + $this->assertEquals(2, $nodes->count()); + $this->assertEquals('Two', $nodes->eq(0)->text()); + $this->assertEquals('Three', $nodes->eq(1)->text()); + + try { + $this->createTestCrawler()->filterXPath('//ol')->siblings(); + $this->fail('->siblings() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->siblings() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testNextAll() + { + $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(1); + $this->assertNotSame($crawler, $crawler->nextAll(), '->nextAll() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->nextAll() returns a new instance of a crawler'); + + $nodes = $crawler->nextAll(); + $this->assertEquals(1, $nodes->count()); + $this->assertEquals('Three', $nodes->eq(0)->text()); + + try { + $this->createTestCrawler()->filterXPath('//ol')->nextAll(); + $this->fail('->nextAll() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->nextAll() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testPreviousAll() + { + $crawler = $this->createTestCrawler()->filterXPath('//li')->eq(2); + $this->assertNotSame($crawler, $crawler->previousAll(), '->previousAll() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->previousAll() returns a new instance of a crawler'); + + $nodes = $crawler->previousAll(); + $this->assertEquals(2, $nodes->count()); + $this->assertEquals('Two', $nodes->eq(0)->text()); + + try { + $this->createTestCrawler()->filterXPath('//ol')->previousAll(); + $this->fail('->previousAll() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->previousAll() throws an \InvalidArgumentException if the node list is empty'); + } + } + + public function testChildren() + { + $crawler = $this->createTestCrawler()->filterXPath('//ul'); + $this->assertNotSame($crawler, $crawler->children(), '->children() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->children() returns a new instance of a crawler'); + + $nodes = $crawler->children(); + $this->assertEquals(3, $nodes->count()); + $this->assertEquals('One', $nodes->eq(0)->text()); + $this->assertEquals('Two', $nodes->eq(1)->text()); + $this->assertEquals('Three', $nodes->eq(2)->text()); + + try { + $this->createTestCrawler()->filterXPath('//ol')->children(); + $this->fail('->children() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->children() throws an \InvalidArgumentException if the node list is empty'); + } + + try { + $crawler = new Crawler('

'); + $crawler->filter('p')->children(); + $this->assertTrue(true, '->children() does not trigger a notice if the node has no children'); + } catch (\PHPUnit\Framework\Error\Notice $e) { + $this->fail('->children() does not trigger a notice if the node has no children'); + } catch (\PHPUnit\Framework\Error\Notice $e) { + $this->fail('->children() does not trigger a notice if the node has no children'); + } + } + + public function testParents() + { + $crawler = $this->createTestCrawler()->filterXPath('//li[1]'); + $this->assertNotSame($crawler, $crawler->parents(), '->parents() returns a new instance of a crawler'); + $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $crawler, '->parents() returns a new instance of a crawler'); + + $nodes = $crawler->parents(); + $this->assertEquals(3, $nodes->count()); + + $nodes = $this->createTestCrawler()->filterXPath('//html')->parents(); + $this->assertEquals(0, $nodes->count()); + + try { + $this->createTestCrawler()->filterXPath('//ol')->parents(); + $this->fail('->parents() throws an \InvalidArgumentException if the node list is empty'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->parents() throws an \InvalidArgumentException if the node list is empty'); + } + } + + /** + * @dataProvider getBaseTagData + */ + public function testBaseTag($baseValue, $linkValue, $expectedUri, $currentUri = null, $description = '') + { + $crawler = new Crawler('', $currentUri); + $this->assertEquals($expectedUri, $crawler->filterXPath('//a')->link()->getUri(), $description); + } + + public function getBaseTagData() + { + return [ + ['http://base.com', 'link', 'http://base.com/link'], + ['//base.com', 'link', 'https://base.com/link', 'https://domain.com', ' tag can use a schema-less URL'], + ['path/', 'link', 'https://domain.com/path/link', 'https://domain.com', ' tag can set a path'], + ['http://base.com', '#', 'http://base.com#', 'http://domain.com/path/link', ' tag does work with links to an anchor'], + ['http://base.com', '', 'http://base.com', 'http://domain.com/path/link', ' tag does work with empty links'], + ]; + } + + /** + * @dataProvider getBaseTagWithFormData + */ + public function testBaseTagWithForm($baseValue, $actionValue, $expectedUri, $currentUri = null, $description = null) + { + $crawler = new Crawler('
', + ['bar' => ['InputFormField', 'bar']], + ], + [ + 'appends the submitted button value but not other submit buttons', + ' + ', + ['foobar' => ['InputFormField', 'foobar']], + ], + [ + 'turns an image input into x and y fields', + '', + ['bar.x' => ['InputFormField', '0'], 'bar.y' => ['InputFormField', '0']], + ], + [ + 'returns textareas', + ' + ', + ['foo' => ['TextareaFormField', 'foo']], + ], + [ + 'returns inputs', + ' + ', + ['foo' => ['InputFormField', 'foo']], + ], + [ + 'returns checkboxes', + ' + ', + ['foo' => ['ChoiceFormField', 'foo']], + ], + [ + 'returns not-checked checkboxes', + ' + ', + ['foo' => ['ChoiceFormField', false]], + ], + [ + 'returns radio buttons', + ' + + ', + ['foo' => ['ChoiceFormField', 'bar']], + ], + [ + 'returns file inputs', + ' + ', + ['foo' => ['FileFormField', ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]]], + ], + ]; + } + + public function testGetFormNode() + { + $dom = new \DOMDocument(); + $dom->loadHTML('
'); + + $form = new Form($dom->getElementsByTagName('input')->item(0), 'http://example.com'); + + $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form'); + } + + public function testGetFormNodeFromNamedForm() + { + $dom = new \DOMDocument(); + $dom->loadHTML('
'); + + $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com'); + + $this->assertSame($dom->getElementsByTagName('form')->item(0), $form->getFormNode(), '->getFormNode() returns the form node associated with this form'); + } + + public function testGetMethod() + { + $form = $this->createForm('
'); + $this->assertEquals('GET', $form->getMethod(), '->getMethod() returns get if no method is defined'); + + $form = $this->createForm('
'); + $this->assertEquals('POST', $form->getMethod(), '->getMethod() returns the method attribute value of the form'); + + $form = $this->createForm('
', 'put'); + $this->assertEquals('PUT', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); + + $form = $this->createForm('
', 'delete'); + $this->assertEquals('DELETE', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); + + $form = $this->createForm('
', 'patch'); + $this->assertEquals('PATCH', $form->getMethod(), '->getMethod() returns the method defined in the constructor if provided'); + } + + public function testGetMethodWithOverride() + { + $form = $this->createForm('
'); + $this->assertEquals('POST', $form->getMethod(), '->getMethod() returns the method attribute value of the form'); + } + + public function testGetSetValue() + { + $form = $this->createForm('
'); + + $this->assertEquals('foo', $form['foo']->getValue(), '->offsetGet() returns the value of a form field'); + + $form['foo'] = 'bar'; + + $this->assertEquals('bar', $form['foo']->getValue(), '->offsetSet() changes the value of a form field'); + + try { + $form['foobar'] = 'bar'; + $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); + } + + try { + $form['foobar']; + $this->fail('->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); + } catch (\InvalidArgumentException $e) { + $this->assertTrue(true, '->offsetSet() throws an \InvalidArgumentException exception if the field does not exist'); + } + } + + public function testDisableValidation() + { + $form = $this->createForm('
+ + + +
'); + + $form->disableValidation(); + + $form['foo[bar]']->select('foo'); + $form['foo[baz]']->select('bar'); + $this->assertEquals('foo', $form['foo[bar]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.'); + $this->assertEquals('bar', $form['foo[baz]']->getValue(), '->disableValidation() disables validation of all ChoiceFormField.'); + } + + public function testOffsetUnset() + { + $form = $this->createForm('
'); + unset($form['foo']); + $this->assertArrayNotHasKey('foo', $form, '->offsetUnset() removes a field'); + } + + public function testOffsetExists() + { + $form = $this->createForm('
'); + + $this->assertArrayHasKey('foo', $form, '->offsetExists() return true if the field exists'); + $this->assertArrayNotHasKey('bar', $form, '->offsetExists() return false if the field does not exist'); + } + + public function testGetValues() + { + $form = $this->createForm('
'); + $this->assertEquals(['foo[bar]' => 'foo', 'bar' => 'bar', 'baz' => []], $form->getValues(), '->getValues() returns all form field values'); + + $form = $this->createForm('
'); + $this->assertEquals(['bar' => 'bar'], $form->getValues(), '->getValues() does not include not-checked checkboxes'); + + $form = $this->createForm('
'); + $this->assertEquals(['bar' => 'bar'], $form->getValues(), '->getValues() does not include file input fields'); + + $form = $this->createForm('
'); + $this->assertEquals(['bar' => 'bar'], $form->getValues(), '->getValues() does not include disabled fields'); + + $form = $this->createForm('
'); + $this->assertEquals(['bar' => 'bar'], $form->getValues(), '->getValues() does not include template fields'); + $this->assertFalse($form->has('foo')); + } + + public function testSetValues() + { + $form = $this->createForm('
'); + $form->setValues(['foo' => false, 'bar' => 'foo']); + $this->assertEquals(['bar' => 'foo'], $form->getValues(), '->setValues() sets the values of fields'); + } + + public function testMultiselectSetValues() + { + $form = $this->createForm('
'); + $form->setValues(['multi' => ['foo', 'bar']]); + $this->assertEquals(['multi' => ['foo', 'bar']], $form->getValues(), '->setValue() sets the values of select'); + } + + public function testGetPhpValues() + { + $form = $this->createForm('
'); + $this->assertEquals(['foo' => ['bar' => 'foo'], 'bar' => 'bar'], $form->getPhpValues(), '->getPhpValues() converts keys with [] to arrays'); + + $form = $this->createForm('
'); + $this->assertEquals(['fo.o' => ['ba.r' => 'foo'], 'ba r' => 'bar'], $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names'); + + $form = $this->createForm('
'); + $this->assertEquals(['fo.o' => ['ba.r' => ['foo', 'ba.z' => 'bar']]], $form->getPhpValues(), '->getPhpValues() preserves periods and spaces in names recursively'); + + $form = $this->createForm('
'); + $this->assertEquals(['foo' => ['bar' => 'foo'], 'bar' => 'bar'], $form->getPhpValues(), "->getPhpValues() doesn't return empty values"); + } + + public function testGetFiles() + { + $form = $this->createForm('
'); + $this->assertEquals([], $form->getFiles(), '->getFiles() returns an empty array if method is get'); + + $form = $this->createForm('
'); + $this->assertEquals(['foo[bar]' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]], $form->getFiles(), '->getFiles() only returns file fields for POST'); + + $form = $this->createForm('
', 'put'); + $this->assertEquals(['foo[bar]' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]], $form->getFiles(), '->getFiles() only returns file fields for PUT'); + + $form = $this->createForm('
', 'delete'); + $this->assertEquals(['foo[bar]' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]], $form->getFiles(), '->getFiles() only returns file fields for DELETE'); + + $form = $this->createForm('
', 'patch'); + $this->assertEquals(['foo[bar]' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]], $form->getFiles(), '->getFiles() only returns file fields for PATCH'); + + $form = $this->createForm('
'); + $this->assertEquals([], $form->getFiles(), '->getFiles() does not include disabled file fields'); + + $form = $this->createForm('
'); + $this->assertEquals([], $form->getFiles(), '->getFiles() does not include template file fields'); + $this->assertFalse($form->has('foo')); + } + + public function testGetPhpFiles() + { + $form = $this->createForm('
'); + $this->assertEquals(['foo' => ['bar' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]]], $form->getPhpFiles(), '->getPhpFiles() converts keys with [] to arrays'); + + $form = $this->createForm('
'); + $this->assertEquals(['f.o o' => ['bar' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]]], $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names'); + + $form = $this->createForm('
'); + $this->assertEquals(['f.o o' => ['bar' => ['ba.z' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0], ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]]]], $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names recursively'); + + $form = $this->createForm('
'); + $files = $form->getPhpFiles(); + + $this->assertSame(0, $files['foo']['bar']['size'], '->getPhpFiles() converts size to int'); + $this->assertSame(4, $files['foo']['bar']['error'], '->getPhpFiles() converts error to int'); + + $form = $this->createForm('
'); + $this->assertEquals(['size' => ['error' => ['name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0]]], $form->getPhpFiles(), '->getPhpFiles() int conversion does not collide with file names'); + } + + /** + * @dataProvider provideGetUriValues + */ + public function testGetUri($message, $form, $values, $uri, $method = null) + { + $form = $this->createForm($form, $method); + $form->setValues($values); + + $this->assertEquals('http://example.com'.$uri, $form->getUri(), '->getUri() '.$message); + } + + public function testGetBaseUri() + { + $dom = new \DOMDocument(); + $dom->loadHTML('
'); + + $nodes = $dom->getElementsByTagName('input'); + $form = new Form($nodes->item($nodes->length - 1), 'http://www.foo.com/'); + $this->assertEquals('http://www.foo.com/foo.php', $form->getUri()); + } + + public function testGetUriWithAnchor() + { + $form = $this->createForm('
', null, 'http://example.com/id/123'); + + $this->assertEquals('http://example.com/id/123#foo', $form->getUri()); + } + + public function testGetUriActionAbsolute() + { + $formHtml = '
'; + + $form = $this->createForm($formHtml); + $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); + + $form = $this->createForm($formHtml, null, 'https://login.foo.com'); + $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); + + $form = $this->createForm($formHtml, null, 'https://login.foo.com/bar/'); + $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); + + // The action URI haven't the same domain Host have an another domain as Host + $form = $this->createForm($formHtml, null, 'https://www.foo.com'); + $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); + + $form = $this->createForm($formHtml, null, 'https://www.foo.com/bar/'); + $this->assertEquals('https://login.foo.com/login.php?login_attempt=1', $form->getUri(), '->getUri() returns absolute URIs set in the action form'); + } + + public function testGetUriAbsolute() + { + $form = $this->createForm('
', null, 'http://localhost/foo/'); + $this->assertEquals('http://localhost/foo/foo', $form->getUri(), '->getUri() returns absolute URIs'); + + $form = $this->createForm('
', null, 'http://localhost/foo/'); + $this->assertEquals('http://localhost/foo', $form->getUri(), '->getUri() returns absolute URIs'); + } + + public function testGetUriWithOnlyQueryString() + { + $form = $this->createForm('
', null, 'http://localhost/foo/bar'); + $this->assertEquals('http://localhost/foo/bar?get=param', $form->getUri(), '->getUri() returns absolute URIs only if the host has been defined in the constructor'); + } + + public function testGetUriWithoutAction() + { + $form = $this->createForm('
', null, 'http://localhost/foo/bar'); + $this->assertEquals('http://localhost/foo/bar', $form->getUri(), '->getUri() returns path if no action defined'); + } + + public function testGetUriWithActionOverride() + { + $form = $this->createForm('
+ + + + '); + $form = new Form($dom->getElementsByTagName('form')->item(0), 'http://example.com'); + + $this->assertInstanceOf('Symfony\Component\DomCrawler\Field\ChoiceFormField', $form->get('option')); + } + + protected function getFormFieldMock($name, $value = null) + { + $field = $this + ->getMockBuilder('Symfony\\Component\\DomCrawler\\Field\\FormField') + ->setMethods(['getName', 'getValue', 'setValue', 'initialize']) + ->disableOriginalConstructor() + ->getMock() + ; + + $field + ->expects($this->any()) + ->method('getName') + ->willReturn($name) + ; + + $field + ->expects($this->any()) + ->method('getValue') + ->willReturn($value) + ; + + return $field; + } + + protected function createForm($form, $method = null, $currentUri = null) + { + $dom = new \DOMDocument(); + @$dom->loadHTML(''.$form.''); + + $xPath = new \DOMXPath($dom); + $nodes = $xPath->query('//input | //button'); + + if (null === $currentUri) { + $currentUri = 'http://example.com/'; + } + + return new Form($nodes->item($nodes->length - 1), $currentUri, $method); + } + + protected function createTestHtml5Form() + { + $dom = new \DOMDocument(); + $dom->loadHTML(' + +

Hello form

+
+
+ +
+ + +
+ +
+
+
+ + + +
+ +
+ +
+
+
+ + +
+
+ + +
+
+
+ + + +
+