Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found
in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219
Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK ! G psysh/.editorconfignu Iw root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
PK ! e{} psysh/Makefilenu Iw PSYSH_SRC = bin src box.json.dist composer.json build/stub
PSYSH_SRC_FILES = $(shell find src -type f -name "*.php")
VERSION = $(shell git describe --tag --always --dirty=-dev)
COMPOSER_OPTS = --no-interaction --no-progress --verbose
COMPOSER_REQUIRE_OPTS = $(COMPOSER_OPTS) --no-update
COMPOSER_UPDATE_OPTS = $(COMPOSER_OPTS) --prefer-stable --no-dev --classmap-authoritative --prefer-dist
# Commands
.PHONY: help clean build dist
.DEFAULT_GOAL := help
help:
@echo "\033[33mUsage:\033[0m\n make TARGET\n\n\033[33mTargets:\033[0m"
@grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[32m%-7s\033[0m %s\n", $$1, $$2}'
clean: ## Clean all created artifacts
rm -rf build/*
rm -rf dist/*
rm -rf vendor-bin/*/vendor/
build: ## Compile PHARs
build: build/psysh/psysh build/psysh-compat/psysh build/psysh-php54/psysh build/psysh-php54-compat/psysh
dist: ## Build tarballs for distribution
dist: dist/psysh-$(VERSION).tar.gz dist/psysh-$(VERSION)-compat.tar.gz dist/psysh-$(VERSION)-php54.tar.gz dist/psysh-$(VERSION)-php54-compat.tar.gz
# All the composer stuffs
composer.lock: composer.json
composer install
touch $@
vendor/autoload.php: composer.lock
composer install
touch $@
vendor/bin/box: vendor/autoload.php
composer bin box install
touch $@
# Lots of PHARs
build/stub: bin/build-stub bin/psysh LICENSE
bin/build-stub
build/psysh: $(PSYSH_SRC) $(PSYSH_SRC_FILES)
rm -rf $@ || true
mkdir $@
cp -R $(PSYSH_SRC) $@/
composer config --working-dir $@ platform.php 7.0
composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) php:'>=7.0.0'
composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS)
build/psysh-compat: $(PSYSH_SRC) $(PSYSH_SRC_FILES)
rm -rf $@ || true
mkdir $@
cp -R $(PSYSH_SRC) $@/
composer config --working-dir $@ platform.php 7.0
composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) php:'>=7.0.0'
composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) symfony/polyfill-iconv symfony/polyfill-mbstring hoa/console
composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS)
build/psysh-php54: $(PSYSH_SRC) $(PSYSH_SRC_FILES)
rm -rf $@ || true
mkdir $@
cp -R $(PSYSH_SRC) $@/
composer config --working-dir $@ platform.php 5.4
composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS)
build/psysh-php54-compat: $(PSYSH_SRC) $(PSYSH_SRC_FILES)
rm -rf $@ || true
mkdir $@
cp -R $(PSYSH_SRC) $@/
composer config --working-dir $@ platform.php 5.4
composer require --working-dir $@ $(COMPOSER_REQUIRE_OPTS) symfony/polyfill-iconv symfony/polyfill-mbstring hoa/console:^2.15
composer update --working-dir $@ $(COMPOSER_UPDATE_OPTS)
build/%/psysh: vendor/bin/box build/%
vendor/bin/box compile --working-dir $(dir $@)
# Dist packages
dist/psysh-$(VERSION).tar.gz: build/psysh/psysh
@mkdir -p $(@D)
tar -C $(dir $<) -czf $@ $(notdir $<)
dist/psysh-$(VERSION)-%.tar.gz: build/psysh-%/psysh
@mkdir -p $(@D)
tar -C $(dir $<) -czf $@ $(notdir $<)
PK ! u u psysh/README.mdnu Iw # PsySH
PsySH is a runtime developer console, interactive debugger and [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) for PHP. Learn more at [psysh.org](http://psysh.org/) and [in the manual](https://github.com/bobthecow/psysh/wiki/Home).
[](https://packagist.org/packages/psy/psysh)
[](https://packagist.org/packages/psy/psysh)
[](http://psysh.org)
[](http://travis-ci.org/bobthecow/psysh)
[](https://styleci.io/repos/4549925)
## [PsySH manual](https://github.com/bobthecow/psysh/wiki/Home)
### [💾 Installation](https://github.com/bobthecow/psysh/wiki/Installation)
* [📕 PHP manual installation](https://github.com/bobthecow/psysh/wiki/PHP-manual)
*
Windows
### [🖥 Usage](https://github.com/bobthecow/psysh/wiki/Usage)
* [✨ Magic variables](https://github.com/bobthecow/psysh/wiki/Magic-variables)
* [⏳ Managing history](https://github.com/bobthecow/psysh/wiki/History)
* [💲 System shell integration](https://github.com/bobthecow/psysh/wiki/Shell-integration)
* [🎥 Tutorials & guides](https://github.com/bobthecow/psysh/wiki/Tutorials)
### [📢 Commands](https://github.com/bobthecow/psysh/wiki/Commands)
### [🛠 Configuration](https://github.com/bobthecow/psysh/wiki/Configuration)
* [🎛 Config options](https://github.com/bobthecow/psysh/wiki/Config-options)
* [📄 Sample config file](https://github.com/bobthecow/psysh/wiki/Sample-config)
### [🔌 Integrations](https://github.com/bobthecow/psysh/wiki/Integrations)
PK ! yC> >
psysh/LICENSEnu Iw The MIT License (MIT)
Copyright (c) 2012-2018 Justin Hileman
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.
PK ! ; ; psysh/phpunit.xml.distnu Iw
./test
./src
PK ! 5_ _ psysh/.travis.ymlnu Iw language: php
sudo: false
matrix:
include:
- php: 5.4
dist: trusty
- php: 5.4
env: 'COMPOSER_FLAGS="--prefer-lowest --prefer-stable"'
dist: trusty
- php: 5.5
dist: trusty
- php: 5.6
- php: 7.0
- php: 7.1
- php: 7.2
- php: hhvm
dist: trusty
allow_failures:
- php: 5.4
env: 'COMPOSER_FLAGS="--prefer-lowest --prefer-stable"'
- php: hhvm
fast_finish: true
install: travis_retry composer update --no-interaction $COMPOSER_FLAGS
script:
- vendor/bin/phpunit --verbose --coverage-clover=coverage.xml
- '[[ $TRAVIS_PHP_VERSION = 7.2* ]] && make build -j 4 || true'
after_success:
- bash <(curl -s https://codecov.io/bash)
before_deploy: make dist -j 4
deploy:
provider: releases
api_key:
secure: LL8koDM1xDqzF9t0URHvmMPyWjojyd4PeZ7IW7XYgyvD6n1H6GYrVAeKCh5wfUKFbwHoa9s5AAn6pLzra00bODVkPTmUH+FSMWz9JKLw9ODAn8HvN7C+IooxmeClGHFZc0TfHfya8/D1E9C1iXtGGEoE/GqtaYq/z0C1DLpO0OU=
file_glob: true
file: dist/psysh-*.tar.gz
skip_cleanup: true
on:
tags: true
repo: bobthecow/psysh
condition: $TRAVIS_PHP_VERSION = 7.2*
PK ! ^ps s " psysh/vendor-bin/box/composer.jsonnu Iw {
"minimum-stability": "dev",
"prefer-stable": true,
"require": {
"humbug/box": "^3.1"
}
}
PK ! _-V V " psysh/vendor-bin/box/composer.locknu Iw {
"_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": "d98ffe050f0ba4e81c2d1a98ca945200",
"packages": [
{
"name": "amphp/amp",
"version": "v2.0.7",
"source": {
"type": "git",
"url": "https://github.com/amphp/amp.git",
"reference": "d561cc9736bc18dd94a2fc9cdae98b616bd92c43"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/amp/zipball/d561cc9736bc18dd94a2fc9cdae98b616bd92c43",
"reference": "d561cc9736bc18dd94a2fc9cdae98b616bd92c43",
"shasum": ""
},
"require": {
"php": ">=7"
},
"require-dev": {
"amphp/phpunit-util": "^1",
"friendsofphp/php-cs-fixer": "^2.3",
"phpstan/phpstan": "^0.8.5",
"phpunit/phpunit": "^6.0.9",
"react/promise": "^2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Amp\\": "lib"
},
"files": [
"lib/functions.php",
"lib/Internal/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
},
{
"name": "Daniel Lowrey",
"email": "rdlowrey@php.net"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "A non-blocking concurrency framework for PHP applications.",
"homepage": "http://amphp.org/amp",
"keywords": [
"async",
"asynchronous",
"awaitable",
"concurrency",
"event",
"event-loop",
"future",
"non-blocking",
"promise"
],
"time": "2018-04-30T20:49:57+00:00"
},
{
"name": "amphp/byte-stream",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/byte-stream.git",
"reference": "1b75b122e6f069e7d102eef065dc192119d99ca7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/byte-stream/zipball/1b75b122e6f069e7d102eef065dc192119d99ca7",
"reference": "1b75b122e6f069e7d102eef065dc192119d99ca7",
"shasum": ""
},
"require": {
"amphp/amp": "^2"
},
"require-dev": {
"amphp/phpunit-util": "^1",
"friendsofphp/php-cs-fixer": "^2.3",
"phpunit/phpunit": "^6"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\ByteStream\\": "lib"
},
"files": [
"lib/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "A stream abstraction to make working with non-blocking I/O simple.",
"homepage": "http://amphp.org/byte-stream",
"keywords": [
"amp",
"amphp",
"async",
"io",
"non-blocking",
"stream"
],
"time": "2018-04-04T05:33:09+00:00"
},
{
"name": "amphp/parallel",
"version": "v0.2.5",
"source": {
"type": "git",
"url": "https://github.com/amphp/parallel.git",
"reference": "732694688461936bec02c0ccf020dfee10c4f7ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/parallel/zipball/732694688461936bec02c0ccf020dfee10c4f7ee",
"reference": "732694688461936bec02c0ccf020dfee10c4f7ee",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"amphp/byte-stream": "^1.2",
"amphp/parser": "^1",
"amphp/process": "^0.2 || ^0.3",
"amphp/sync": "^1.0.1"
},
"require-dev": {
"amphp/phpunit-util": "^1",
"friendsofphp/php-cs-fixer": "^2.3",
"phpunit/phpunit": "^6"
},
"suggest": {
"ext-pthreads": "Required for thread contexts"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\Parallel\\": "lib"
},
"files": [
"lib/Worker/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Stephen Coakley",
"email": "me@stephencoakley.com"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "Parallel processing component for Amp.",
"homepage": "https://github.com/amphp/parallel",
"keywords": [
"async",
"asynchronous",
"concurrent",
"multi-processing",
"multi-threading"
],
"time": "2018-03-21T14:37:51+00:00"
},
{
"name": "amphp/parallel-functions",
"version": "v0.1.2",
"source": {
"type": "git",
"url": "https://github.com/amphp/parallel-functions.git",
"reference": "999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/parallel-functions/zipball/999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48",
"reference": "999ba8a00adaf4d1fd3a7cb40bf7e565e507ff48",
"shasum": ""
},
"require": {
"amphp/amp": "^2.0.3",
"amphp/parallel": "^0.1.8 || ^0.2",
"opis/closure": "^3.0.7",
"php": ">=7"
},
"require-dev": {
"amphp/phpunit-util": "^1.0",
"friendsofphp/php-cs-fixer": "^2.9",
"phpunit/phpunit": "^6.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\ParallelFunctions\\": "src"
},
"files": [
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
}
],
"description": "Parallel processing made simple.",
"time": "2017-12-17T18:33:29+00:00"
},
{
"name": "amphp/parser",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/amphp/parser.git",
"reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
"reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
"shasum": ""
},
"require": {
"php": ">=7"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.3",
"phpunit/phpunit": "^6"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\Parser\\": "lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "A generator parser to make streaming parsers simple.",
"homepage": "https://github.com/amphp/parser",
"keywords": [
"async",
"non-blocking",
"parser",
"stream"
],
"time": "2017-06-06T05:29:10+00:00"
},
{
"name": "amphp/process",
"version": "v0.3.3",
"source": {
"type": "git",
"url": "https://github.com/amphp/process.git",
"reference": "b795d20a7f6d5a0637128a02be613f520f1705fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/process/zipball/b795d20a7f6d5a0637128a02be613f520f1705fc",
"reference": "b795d20a7f6d5a0637128a02be613f520f1705fc",
"shasum": ""
},
"require": {
"amphp/amp": "^2",
"amphp/byte-stream": "^1",
"php": ">=7"
},
"require-dev": {
"amphp/phpunit-util": "^1",
"friendsofphp/php-cs-fixer": "^2.3",
"phpunit/phpunit": "^6"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\Process\\": "lib"
},
"files": [
"lib/constants.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bob Weinand",
"email": "bobwei9@hotmail.com"
},
{
"name": "Niklas Keller",
"email": "me@kelunik.com"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "Asynchronous process manager.",
"homepage": "https://github.com/amphp/process",
"time": "2018-04-08T18:55:42+00:00"
},
{
"name": "amphp/sync",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/amphp/sync.git",
"reference": "a1d8f244eb19e3e2a96abc4686cebc80995bbc90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amphp/sync/zipball/a1d8f244eb19e3e2a96abc4686cebc80995bbc90",
"reference": "a1d8f244eb19e3e2a96abc4686cebc80995bbc90",
"shasum": ""
},
"require": {
"amphp/amp": "^2"
},
"require-dev": {
"amphp/phpunit-util": "^1",
"friendsofphp/php-cs-fixer": "^2.3",
"phpunit/phpunit": "^6"
},
"type": "library",
"autoload": {
"psr-4": {
"Amp\\Sync\\": "lib"
},
"files": [
"lib/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Stephen Coakley",
"email": "me@stephencoakley.com"
},
{
"name": "Aaron Piotrowski",
"email": "aaron@trowski.com"
}
],
"description": "Mutex, Semaphore, and other synchronization tools for Amp.",
"homepage": "https://github.com/amphp/sync",
"keywords": [
"async",
"asynchronous",
"mutex",
"semaphore",
"synchronization"
],
"time": "2017-11-29T21:48:53+00:00"
},
{
"name": "beberlei/assert",
"version": "v2.9.5",
"source": {
"type": "git",
"url": "https://github.com/beberlei/assert.git",
"reference": "c07fe163d6a3b3e4b1275981ec004397954afa89"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/beberlei/assert/zipball/c07fe163d6a3b3e4b1275981ec004397954afa89",
"reference": "c07fe163d6a3b3e4b1275981ec004397954afa89",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"php": ">=5.3"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.1.1",
"phpunit/phpunit": "^4.8.35|^5.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Assert\\": "lib/Assert"
},
"files": [
"lib/Assert/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de",
"role": "Lead Developer"
},
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com",
"role": "Collaborator"
}
],
"description": "Thin assertion library for input validation in business models.",
"keywords": [
"assert",
"assertion",
"validation"
],
"time": "2018-04-16T11:18:27+00:00"
},
{
"name": "composer/ca-bundle",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
"reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/ca-bundle/zipball/d2c0a83b7533d6912e8d516756ebd34f893e9169",
"reference": "d2c0a83b7533d6912e8d516756ebd34f893e9169",
"shasum": ""
},
"require": {
"ext-openssl": "*",
"ext-pcre": "*",
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
"psr/log": "^1.0",
"symfony/process": "^2.5 || ^3.0 || ^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\CaBundle\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
"keywords": [
"cabundle",
"cacert",
"certificate",
"ssl",
"tls"
],
"time": "2018-03-29T19:57:20+00:00"
},
{
"name": "composer/composer",
"version": "1.6.5",
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
"reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/composer/zipball/b184a92419cc9a9c4c6a09db555a94d441cb11c9",
"reference": "b184a92419cc9a9c4c6a09db555a94d441cb11c9",
"shasum": ""
},
"require": {
"composer/ca-bundle": "^1.0",
"composer/semver": "^1.0",
"composer/spdx-licenses": "^1.2",
"justinrainbow/json-schema": "^3.0 || ^4.0 || ^5.0",
"php": "^5.3.2 || ^7.0",
"psr/log": "^1.0",
"seld/cli-prompt": "^1.0",
"seld/jsonlint": "^1.4",
"seld/phar-utils": "^1.0",
"symfony/console": "^2.7 || ^3.0 || ^4.0",
"symfony/filesystem": "^2.7 || ^3.0 || ^4.0",
"symfony/finder": "^2.7 || ^3.0 || ^4.0",
"symfony/process": "^2.7 || ^3.0 || ^4.0"
},
"conflict": {
"symfony/console": "2.8.38"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7",
"phpunit/phpunit-mock-objects": "^2.3 || ^3.0"
},
"suggest": {
"ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
"ext-zip": "Enabling the zip extension allows you to unzip archives",
"ext-zlib": "Allow gzip compression of HTTP requests"
},
"bin": [
"bin/composer"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.6-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\": "src/Composer"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.",
"homepage": "https://getcomposer.org/",
"keywords": [
"autoload",
"dependency",
"package"
],
"time": "2018-05-04T09:44:59+00:00"
},
{
"name": "composer/semver",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "c7cb9a2095a074d131b65a8a0cd294479d785573"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/c7cb9a2095a074d131b65a8a0cd294479d785573",
"reference": "c7cb9a2095a074d131b65a8a0cd294479d785573",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.5 || ^5.0.5",
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"time": "2016-08-30T16:08:34+00:00"
},
{
"name": "composer/spdx-licenses",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/composer/spdx-licenses.git",
"reference": "cb17687e9f936acd7e7245ad3890f953770dec1b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/spdx-licenses/zipball/cb17687e9f936acd7e7245ad3890f953770dec1b",
"reference": "cb17687e9f936acd7e7245ad3890f953770dec1b",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5",
"phpunit/phpunit-mock-objects": "2.3.0 || ^3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Spdx\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "SPDX licenses list and validation library.",
"keywords": [
"license",
"spdx",
"validator"
],
"time": "2018-04-30T10:33:04+00:00"
},
{
"name": "composer/xdebug-handler",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/c919dc6c62e221fc6406f861ea13433c0aa24f08",
"reference": "c919dc6c62e221fc6406f861ea13433c0aa24f08",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0",
"psr/log": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Composer\\XdebugHandler\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "John Stevenson",
"email": "john-stevenson@blueyonder.co.uk"
}
],
"description": "Restarts a process without xdebug.",
"keywords": [
"Xdebug",
"performance"
],
"time": "2018-04-11T15:42:36+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": "herrera-io/annotations",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/kherge-abandoned/php-annotations.git",
"reference": "7d8b9a536da7f12aad8de7f28b2cb5266bde8da1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kherge-abandoned/php-annotations/zipball/7d8b9a536da7f12aad8de7f28b2cb5266bde8da1",
"reference": "7d8b9a536da7f12aad8de7f28b2cb5266bde8da1",
"shasum": ""
},
"require": {
"doctrine/annotations": "~1.0",
"php": ">=5.3.3"
},
"require-dev": {
"herrera-io/phpunit-test-case": "1.*",
"phpunit/phpunit": "3.7.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-0": {
"Herrera\\Annotations": "src/lib"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kevin Herrera",
"email": "kevin@herrera.io",
"homepage": "http://kevin.herrera.io"
}
],
"description": "A tokenizer for Doctrine annotations.",
"homepage": "https://github.com/herrera-io/php-annotations",
"keywords": [
"annotations",
"doctrine",
"tokenizer"
],
"abandoned": true,
"time": "2014-02-03T17:34:08+00:00"
},
{
"name": "humbug/box",
"version": "3.0.0-alpha.5",
"source": {
"type": "git",
"url": "https://github.com/humbug/box.git",
"reference": "26b3f481e3b375f55c0644f501b831f7c05d8058"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/humbug/box/zipball/26b3f481e3b375f55c0644f501b831f7c05d8058",
"reference": "26b3f481e3b375f55c0644f501b831f7c05d8058",
"shasum": ""
},
"require": {
"amphp/parallel-functions": "^0.1.2",
"beberlei/assert": "^2.8",
"composer/composer": "^1.6",
"composer/xdebug-handler": "^1.1.0",
"ext-phar": "*",
"herrera-io/annotations": "~1.0",
"humbug/php-scoper": "^1.0@dev",
"justinrainbow/json-schema": "^5.2",
"nikic/iter": "^1.6",
"php": "^7.1",
"phpseclib/phpseclib": "~2.0",
"seld/jsonlint": "^1.6",
"symfony/console": "^3.4 || ^4.0",
"symfony/filesystem": "^3.4 || ^4.0",
"symfony/finder": "^3.4 || ^4.0",
"symfony/var-dumper": "^3.4 || ^4.0",
"webmozart/path-util": "^2.3"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.2",
"infection/infection": "^0.8",
"mikey179/vfsstream": "^1.1",
"phpunit/phpunit": "^7.0"
},
"suggest": {
"ext-openssl": "To accelerate private key generation."
},
"bin": [
"bin/box"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
},
"bamarni-bin": {
"bin-links": false
}
},
"autoload": {
"psr-4": {
"KevinGH\\Box\\": "src"
},
"files": [
"src/FileSystem/file_system.php",
"src/functions.php"
],
"exclude-from-classmap": [
"/Test/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kevin Herrera",
"email": "kevin@herrera.io",
"homepage": "http://kevin.herrera.io"
},
{
"name": "Théo Fidry",
"email": "theo.fidry@gmail.com"
}
],
"description": "Fast, zero config application bundler with PHARs.",
"keywords": [
"phar"
],
"time": "2018-05-04T22:04:10+00:00"
},
{
"name": "humbug/php-scoper",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/humbug/php-scoper.git",
"reference": "450fe36a7457847d0cb431e7379b5df9d05992a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/humbug/php-scoper/zipball/450fe36a7457847d0cb431e7379b5df9d05992a4",
"reference": "450fe36a7457847d0cb431e7379b5df9d05992a4",
"shasum": ""
},
"require": {
"nikic/php-parser": "^3.0",
"ocramius/package-versions": "^1.1",
"padraic/phar-updater": "^1.0",
"php": "^7.1",
"roave/better-reflection": "^2.0",
"symfony/console": "^3.2 || ^4.0",
"symfony/filesystem": "^3.2 || ^4.0",
"symfony/finder": "^3.2 || ^4.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.1",
"phpunit/phpunit": "^6.1"
},
"bin": [
"bin/php-scoper"
],
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": false
},
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Humbug\\PhpScoper\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
},
{
"name": "Théo Fidry",
"email": "theo.fidry@gmail.com"
},
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com"
}
],
"description": "Prefixes all PHP namespaces in a file or directory.",
"time": "2018-04-25T21:59:07+00:00"
},
{
"name": "justinrainbow/json-schema",
"version": "5.2.7",
"source": {
"type": "git",
"url": "https://github.com/justinrainbow/json-schema.git",
"reference": "8560d4314577199ba51bf2032f02cd1315587c23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/justinrainbow/json-schema/zipball/8560d4314577199ba51bf2032f02cd1315587c23",
"reference": "8560d4314577199ba51bf2032f02cd1315587c23",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.1",
"json-schema/json-schema-test-suite": "1.2.0",
"phpunit/phpunit": "^4.8.35"
},
"bin": [
"bin/validate-json"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.0.x-dev"
}
},
"autoload": {
"psr-4": {
"JsonSchema\\": "src/JsonSchema/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bruno Prieto Reis",
"email": "bruno.p.reis@gmail.com"
},
{
"name": "Justin Rainbow",
"email": "justin.rainbow@gmail.com"
},
{
"name": "Igor Wiedler",
"email": "igor@wiedler.ch"
},
{
"name": "Robert Schönthal",
"email": "seroscho@googlemail.com"
}
],
"description": "A library to validate a json schema.",
"homepage": "https://github.com/justinrainbow/json-schema",
"keywords": [
"json",
"schema"
],
"time": "2018-02-14T22:26:30+00:00"
},
{
"name": "nikic/iter",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/iter.git",
"reference": "fed36b417ea93fe9b4b7cb2e2abf98d91092564c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/iter/zipball/fed36b417ea93fe9b4b7cb2e2abf98d91092564c",
"reference": "fed36b417ea93fe9b4b7cb2e2abf98d91092564c",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0|~5.0"
},
"type": "library",
"autoload": {
"files": [
"src/bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Nikita Popov",
"email": "nikic@php.net"
}
],
"description": "Iteration primitives using generators",
"keywords": [
"functional",
"generator",
"iterator"
],
"time": "2017-11-10T22:56:03+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": "ocramius/package-versions",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/PackageVersions.git",
"reference": "4489d5002c49d55576fa0ba786f42dbb009be46f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Ocramius/PackageVersions/zipball/4489d5002c49d55576fa0ba786f42dbb009be46f",
"reference": "4489d5002c49d55576fa0ba786f42dbb009be46f",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0.0",
"php": "^7.1.0"
},
"require-dev": {
"composer/composer": "^1.6.3",
"ext-zip": "*",
"infection/infection": "^0.7.1",
"phpunit/phpunit": "^7.0.0"
},
"type": "composer-plugin",
"extra": {
"class": "PackageVersions\\Installer",
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"PackageVersions\\": "src/PackageVersions"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com"
}
],
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"time": "2018-02-05T13:05:30+00:00"
},
{
"name": "opis/closure",
"version": "3.0.12",
"source": {
"type": "git",
"url": "https://github.com/opis/closure.git",
"reference": "507a28d15e79258d404ba76e73976ba895d0eb11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/opis/closure/zipball/507a28d15e79258d404ba76e73976ba895d0eb11",
"reference": "507a28d15e79258d404ba76e73976ba895d0eb11",
"shasum": ""
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"jeremeamia/superclosure": "^2.0",
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Opis\\Closure\\": "src/"
},
"files": [
"functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marius Sarca",
"email": "marius.sarca@gmail.com"
}
],
"description": "A library that can be used to serialize closures (anonymous functions) and arbitrary objects.",
"homepage": "http://www.opis.io/closure",
"keywords": [
"anonymous functions",
"closure",
"function",
"serializable",
"serialization",
"serialize"
],
"time": "2018-02-23T08:08:14+00:00"
},
{
"name": "padraic/humbug_get_contents",
"version": "1.1.2",
"source": {
"type": "git",
"url": "https://github.com/humbug/file_get_contents.git",
"reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/humbug/file_get_contents/zipball/dcb086060c9dd6b2f51d8f7a895500307110b7a7",
"reference": "dcb086060c9dd6b2f51d8f7a895500307110b7a7",
"shasum": ""
},
"require": {
"composer/ca-bundle": "^1.0",
"ext-openssl": "*",
"php": "^5.3 || ^7.0 || ^7.1 || ^7.2"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.1",
"mikey179/vfsstream": "^1.6",
"phpunit/phpunit": "^4.8 || ^5.7 || ^6.5"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": false
},
"branch-alias": {
"dev-master": "2.0-dev"
}
},
"autoload": {
"psr-4": {
"Humbug\\": "src/"
},
"files": [
"src/function.php",
"src/functions.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Padraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
},
{
"name": "Théo Fidry",
"email": "theo.fidry@gmail.com"
}
],
"description": "Secure wrapper for accessing HTTPS resources with file_get_contents for PHP 5.3+",
"homepage": "https://github.com/padraic/file_get_contents",
"keywords": [
"download",
"file_get_contents",
"http",
"https",
"ssl",
"tls"
],
"time": "2018-02-12T18:47:17+00:00"
},
{
"name": "padraic/phar-updater",
"version": "v1.0.6",
"source": {
"type": "git",
"url": "https://github.com/humbug/phar-updater.git",
"reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/humbug/phar-updater/zipball/d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1",
"reference": "d01d3b8f26e541ac9b9eeba1e18d005d852f7ff1",
"shasum": ""
},
"require": {
"padraic/humbug_get_contents": "^1.0",
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"Humbug\\SelfUpdate\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
}
],
"description": "A thing to make PHAR self-updating easy and secure.",
"keywords": [
"humbug",
"phar",
"self-update",
"update"
],
"time": "2018-03-30T12:52:15+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": "4.3.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "94fd0001232e47129dd3504189fa1c7225010d08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/94fd0001232e47129dd3504189fa1c7225010d08",
"reference": "94fd0001232e47129dd3504189fa1c7225010d08",
"shasum": ""
},
"require": {
"php": "^7.0",
"phpdocumentor/reflection-common": "^1.0.0",
"phpdocumentor/type-resolver": "^0.4.0",
"webmozart/assert": "^1.0"
},
"require-dev": {
"doctrine/instantiator": "~1.0.5",
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^6.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": [
"src/"
]
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "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-30T07:14:17+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": "phpseclib/phpseclib",
"version": "2.0.11",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "7053f06f91b3de78e143d430e55a8f7889efc08b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/7053f06f91b3de78e143d430e55a8f7889efc08b",
"reference": "7053f06f91b3de78e143d430e55a8f7889efc08b",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "^4.8.35|^5.7|^6.0",
"sami/sami": "~2.0",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"type": "library",
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib\\": "phpseclib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"homepage": "http://phpseclib.sourceforge.net",
"keywords": [
"BigInteger",
"aes",
"asn.1",
"asn1",
"blowfish",
"crypto",
"cryptography",
"encryption",
"rsa",
"security",
"sftp",
"signature",
"signing",
"ssh",
"twofish",
"x.509",
"x509"
],
"time": "2018-04-15T16:55:05+00:00"
},
{
"name": "psr/log",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
"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": "2016-10-10T12:19:37+00:00"
},
{
"name": "roave/better-reflection",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/Roave/BetterReflection.git",
"reference": "efc45b50cb52d5eeaacab15741376e981e28738b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Roave/BetterReflection/zipball/efc45b50cb52d5eeaacab15741376e981e28738b",
"reference": "efc45b50cb52d5eeaacab15741376e981e28738b",
"shasum": ""
},
"require": {
"nikic/php-parser": "^3.1.1",
"php": ">=7.1.0,<7.3.0",
"phpdocumentor/reflection-docblock": "^4.1.1",
"phpdocumentor/type-resolver": "^0.4.0",
"roave/signature": "^1.0"
},
"require-dev": {
"phpunit/phpunit": "^6.3.0"
},
"suggest": {
"composer/composer": "Required to use the ComposerSourceLocator"
},
"type": "library",
"autoload": {
"psr-4": {
"Roave\\BetterReflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Marco Pivetta",
"email": "ocramius@gmail.com",
"homepage": "http://ocramius.github.io/"
},
{
"name": "James Titcumb",
"email": "james@asgrim.com",
"homepage": "https://github.com/asgrim"
},
{
"name": "Gary Hockin",
"email": "gary@roave.com",
"homepage": "https://github.com/geeh"
},
{
"name": "Jaroslav Hanslík",
"email": "kukulich@kukulich.cz",
"homepage": "https://github.com/kukulich"
}
],
"description": "Better Reflection - an improved code reflection API",
"time": "2018-02-05T08:08:57+00:00"
},
{
"name": "roave/signature",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/Roave/Signature.git",
"reference": "bed4ecbdd7f312ab6bb39561ac191f520bcee386"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Roave/Signature/zipball/bed4ecbdd7f312ab6bb39561ac191f520bcee386",
"reference": "bed4ecbdd7f312ab6bb39561ac191f520bcee386",
"shasum": ""
},
"require": {
"php": "^7.0|^7.1"
},
"require-dev": {
"phpunit/phpunit": "^5.6"
},
"type": "library",
"autoload": {
"psr-4": {
"Roave\\Signature\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Sign and verify stuff",
"time": "2017-02-17T13:53:21+00:00"
},
{
"name": "seld/cli-prompt",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/cli-prompt.git",
"reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/cli-prompt/zipball/a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
"reference": "a19a7376a4689d4d94cab66ab4f3c816019ba8dd",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\CliPrompt\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "Allows you to prompt for user input on the command line, and optionally hide the characters they type",
"keywords": [
"cli",
"console",
"hidden",
"input",
"prompt"
],
"time": "2017-03-18T11:32:45+00:00"
},
{
"name": "seld/jsonlint",
"version": "1.7.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/jsonlint.git",
"reference": "d15f59a67ff805a44c50ea0516d2341740f81a38"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/jsonlint/zipball/d15f59a67ff805a44c50ea0516d2341740f81a38",
"reference": "d15f59a67ff805a44c50ea0516d2341740f81a38",
"shasum": ""
},
"require": {
"php": "^5.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
},
"bin": [
"bin/jsonlint"
],
"type": "library",
"autoload": {
"psr-4": {
"Seld\\JsonLint\\": "src/Seld/JsonLint/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "JSON Linter",
"keywords": [
"json",
"linter",
"parser",
"validator"
],
"time": "2018-01-24T12:46:19+00:00"
},
{
"name": "seld/phar-utils",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/phar-utils.git",
"reference": "7009b5139491975ef6486545a39f3e6dad5ac30a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/7009b5139491975ef6486545a39f3e6dad5ac30a",
"reference": "7009b5139491975ef6486545a39f3e6dad5ac30a",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Seld\\PharUtils\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be"
}
],
"description": "PHAR file format utilities, for when PHP phars you up",
"keywords": [
"phra"
],
"time": "2015-10-13T18:44:15+00:00"
},
{
"name": "symfony/console",
"version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
"reference": "3e820bc2c520a87ca209ad8fa961c97f42e0b4ae",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/dependency-injection": "<3.4",
"symfony/process": "<3.3"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "~3.4|~4.0",
"symfony/dependency-injection": "~3.4|~4.0",
"symfony/event-dispatcher": "~3.4|~4.0",
"symfony/lock": "~3.4|~4.0",
"symfony/process": "~3.4|~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": "4.0-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-04-30T01:23:47+00:00"
},
{
"name": "symfony/filesystem",
"version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21",
"reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Component\\Filesystem\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-02-22T10:50:29+00:00"
},
{
"name": "symfony/finder",
"version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"reference": "ca27c02b7a3fef4828c998c2ff9ba7aae1641c49",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-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-04-04T05:10:37+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "3296adf6a6454a050679cde90f95350ad604b171"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/3296adf6a6454a050679cde90f95350ad604b171",
"reference": "3296adf6a6454a050679cde90f95350ad604b171",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8-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-04-26T10:06:28+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/a4576e282d782ad82397f3e4ec1df8e0f0cafb46",
"reference": "a4576e282d782ad82397f3e4ec1df8e0f0cafb46",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.8-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
},
"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 backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2018-04-26T10:06:28+00:00"
},
{
"name": "symfony/process",
"version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25",
"reference": "d7dc1ee5dfe9f732cb1bba7310f5b99f2b7a6d25",
"shasum": ""
},
"require": {
"php": "^7.1.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-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-04-03T05:24:00+00:00"
},
{
"name": "symfony/var-dumper",
"version": "v4.0.9",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/3c34cf3f4bbac9e003d9325225e9ef1a49180a18",
"reference": "3c34cf3f4bbac9e003d9325225e9ef1a49180a18",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php72": "~1.5"
},
"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"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.0-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-04-26T16:12:06+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"
},
{
"name": "webmozart/path-util",
"version": "2.3.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/path-util.git",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/path-util/zipball/d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"reference": "d939f7edc24c9a1bb9c0dee5cb05d8e859490725",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"webmozart/assert": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "^4.6",
"sebastian/version": "^1.0.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.3-dev"
}
},
"autoload": {
"psr-4": {
"Webmozart\\PathUtil\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.",
"time": "2015-12-17T08:42:14+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "dev",
"stability-flags": {
"humbug/box": 15
},
"prefer-stable": true,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}
PK ! | psysh/composer.jsonnu Iw {
"name": "psy/psysh",
"description": "An interactive shell for modern PHP.",
"type": "library",
"keywords": ["console", "interactive", "shell", "repl"],
"homepage": "http://psysh.org",
"license": "MIT",
"authors": [
{
"name": "Justin Hileman",
"email": "justin@justinhileman.info",
"homepage": "http://justinhileman.com"
}
],
"require": {
"php": ">=5.4.0",
"ext-json": "*",
"ext-tokenizer": "*",
"symfony/console": "~2.3.10|^2.4.2|~3.0|~4.0|~5.0",
"symfony/var-dumper": "~2.7|~3.0|~4.0|~5.0",
"nikic/php-parser": "~1.3|~2.0|~3.0|~4.0",
"dnoegel/php-xdg-base-dir": "0.1.*",
"jakub-onderka/php-console-highlighter": "0.3.*|0.4.*"
},
"require-dev": {
"phpunit/phpunit": "~4.8.35|~5.0|~6.0|~7.0",
"hoa/console": "~2.15|~3.16",
"bamarni/composer-bin-plugin": "^1.2"
},
"suggest": {
"ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)",
"ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.",
"ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history.",
"ext-pdo-sqlite": "The doc command requires SQLite to work.",
"hoa/console": "A pure PHP readline implementation. You'll want this if your PHP install doesn't already support readline or libedit."
},
"autoload": {
"files": ["src/functions.php"],
"psr-4": {
"Psy\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Psy\\Test\\": "test/"
}
},
"bin": ["bin/psysh"],
"extra": {
"branch-alias": {
"dev-develop": "0.9.x-dev"
}
}
}
PK ! V psysh/bin/psyshnu ̗ #!/usr/bin/env php
$arg) {
if ($arg === '--cwd') {
if ($i >= count($argv) - 1) {
echo 'Missing --cwd argument.' . PHP_EOL;
exit(1);
}
$cwd = $argv[$i + 1];
break;
}
if (preg_match('/^--cwd=/', $arg)) {
$cwd = substr($arg, 6);
break;
}
}
// Or fall back to the actual cwd
if (!isset($cwd)) {
$cwd = getcwd();
}
$cwd = str_replace('\\', '/', $cwd);
$chunks = explode('/', $cwd);
while (!empty($chunks)) {
$path = implode('/', $chunks);
// Find composer.json
if (is_file($path . '/composer.json')) {
if ($cfg = json_decode(file_get_contents($path . '/composer.json'), true)) {
if (isset($cfg['name']) && $cfg['name'] === 'psy/psysh') {
// We're inside the psysh project. Let's use the local
// Composer autoload.
if (is_file($path . '/vendor/autoload.php')) {
require $path . '/vendor/autoload.php';
}
return;
}
}
}
// Or a composer.lock
if (is_file($path . '/composer.lock')) {
if ($cfg = json_decode(file_get_contents($path . '/composer.lock'), true)) {
foreach (array_merge($cfg['packages'], $cfg['packages-dev']) as $pkg) {
if (isset($pkg['name']) && $pkg['name'] === 'psy/psysh') {
// We're inside a project which requires psysh. We'll
// use the local Composer autoload.
if (is_file($path . '/vendor/autoload.php')) {
require $path . '/vendor/autoload.php';
}
return;
}
}
}
}
array_pop($chunks);
}
});
// We didn't find an autoloader for a local version, so use the autoloader that
// came with this script.
if (!class_exists('Psy\Shell')) {
/* <<< */
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
require __DIR__ . '/../vendor/autoload.php';
} elseif (is_file(__DIR__ . '/../../../autoload.php')) {
require __DIR__ . '/../../../autoload.php';
} else {
echo 'PsySH dependencies not found, be sure to run `composer install`.' . PHP_EOL;
echo 'See https://getcomposer.org to get Composer.' . PHP_EOL;
exit(1);
}
/* >>> */
}
// If the psysh binary was included directly, assume they just wanted an
// autoloader and bail early.
//
// Keep this PHP 5.3 code around for a while in case someone is using a globally
// installed psysh as a bin launcher for older local versions.
if (version_compare(PHP_VERSION, '5.3.6', '<')) {
$trace = debug_backtrace();
} elseif (version_compare(PHP_VERSION, '5.4.0', '<')) {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
} else {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
}
if (Psy\Shell::isIncluded($trace)) {
unset($trace);
return;
}
// Clean up after ourselves.
unset($trace);
// If the local version is too old, we can't do this
if (!function_exists('Psy\bin')) {
$argv = $_SERVER['argv'];
$first = array_shift($argv);
if (preg_match('/php(\.exe)?$/', $first)) {
array_shift($argv);
}
array_unshift($argv, 'vendor/bin/psysh');
echo 'A local PsySH dependency was found, but it cannot be loaded. Please update to' . PHP_EOL;
echo 'the latest version, or run the local copy directly, e.g.:' . PHP_EOL;
echo PHP_EOL;
echo ' ' . implode(' ', $argv) . PHP_EOL;
exit(1);
}
// And go!
call_user_func(Psy\bin());
PK ! psysh/bin/build-stubnu ȯ #!/usr/bin/env php
>> \*/}sm', $autoload, $content);
$content = preg_replace('/\\(c\\) .*?with this source code./sm', $license, $content);
$content .= '__HALT_COMPILER();';
@mkdir(dirname(__DIR__) . '/build');
file_put_contents(dirname(__DIR__) . '/build/stub', $content);
PK ! y
psysh/.php_csnu Iw in(__DIR__)
->name('.php_cs')
->name('build-manual')
->name('build-phar')
->exclude('build-vendor');
$header = <<setRules(array(
'@Symfony' => true,
'array_syntax' => array('syntax' => 'short'),
'binary_operator_spaces' => false,
'concat_space' => array('spacing' => 'one'),
'header_comment' => array('header' => $header),
'increment_style' => array('style' => 'post'),
'method_argument_space' => array('keep_multiple_spaces_after_comma' => true),
'ordered_imports' => true,
'pre_increment' => false,
'yoda_style' => false,
))
->setFinder($finder);
PK ! 1$ psysh/.phan/config.phpnu Iw [
'src/',
'vendor/dnoegel/php-xdg-base-dir/src/',
'vendor/doctrine/instantiator/src/',
'vendor/hoa/console/',
'vendor/jakub-onderka/php-console-color/src/',
'vendor/jakub-onderka/php-console-highlighter/src/',
'vendor/nikic/php-parser/lib/',
'vendor/phpdocumentor/reflection-docblock/',
'vendor/symfony/console/',
'vendor/symfony/filesystem/',
'vendor/symfony/finder/',
'vendor/symfony/var-dumper/',
],
// A directory list that defines files that will be excluded
// from static analysis, but whose class and method
// information should be included.
//
// Generally, you'll want to include the directories for
// third-party code (such as "vendor/") in this list.
//
// n.b.: If you'd like to parse but not analyze 3rd
// party code, directories containing that code
// should be added to both the `directory_list`
// and `exclude_analysis_directory_list` arrays.
"exclude_analysis_directory_list" => [
'vendor/'
],
];
PK ! g psysh/.github/CONTRIBUTING.mdnu Iw ## Code style
Please make your code look like the other code in the project.
PsySH follows [PSR-1](http://php-fig.org/psr/psr-1/) and [PSR-2](http://php-fig.org/psr/psr-2/). The easiest way to do make sure you're following the coding standard is to [install `php-cs-fixer`](https://github.com/friendsofphp/php-cs-fixer) and run `php-cs-fixer fix` before committing.
## Branching model
Please branch off and send pull requests to the `develop` branch.
PK ! 9Zه ه psysh/src/Configuration.phpnu Iw setColorMode(self::COLOR_MODE_AUTO);
// explicit configFile option
if (isset($config['configFile'])) {
$this->configFile = $config['configFile'];
} elseif ($configFile = \getenv('PSYSH_CONFIG')) {
$this->configFile = $configFile;
}
// legacy baseDir option
if (isset($config['baseDir'])) {
$msg = "The 'baseDir' configuration option is deprecated; " .
"please specify 'configDir' and 'dataDir' options instead";
throw new DeprecatedException($msg);
}
unset($config['configFile'], $config['baseDir']);
// go go gadget, config!
$this->loadConfig($config);
$this->init();
}
/**
* Initialize the configuration.
*
* This checks for the presence of Readline and Pcntl extensions.
*
* If a config file is available, it will be loaded and merged with the current config.
*
* If no custom config file was specified and a local project config file
* is available, it will be loaded and merged with the current config.
*/
public function init()
{
// feature detection
$this->hasReadline = \function_exists('readline');
$this->hasPcntl = \function_exists('pcntl_signal') && \function_exists('posix_getpid');
if ($configFile = $this->getConfigFile()) {
$this->loadConfigFile($configFile);
}
if (!$this->configFile && $localConfig = $this->getLocalConfigFile()) {
$this->loadConfigFile($localConfig);
}
}
/**
* Get the current PsySH config file.
*
* If a `configFile` option was passed to the Configuration constructor,
* this file will be returned. If not, all possible config directories will
* be searched, and the first `config.php` or `rc.php` file which exists
* will be returned.
*
* If you're trying to decide where to put your config file, pick
*
* ~/.config/psysh/config.php
*
* @return string
*/
public function getConfigFile()
{
if (isset($this->configFile)) {
return $this->configFile;
}
$files = ConfigPaths::getConfigFiles(['config.php', 'rc.php'], $this->configDir);
if (!empty($files)) {
if ($this->warnOnMultipleConfigs && \count($files) > 1) {
$msg = \sprintf('Multiple configuration files found: %s. Using %s', \implode($files, ', '), $files[0]);
\trigger_error($msg, E_USER_NOTICE);
}
return $files[0];
}
}
/**
* Get the local PsySH config file.
*
* Searches for a project specific config file `.psysh.php` in the current
* working directory.
*
* @return string
*/
public function getLocalConfigFile()
{
$localConfig = \getcwd() . '/.psysh.php';
if (@\is_file($localConfig)) {
return $localConfig;
}
}
/**
* Load configuration values from an array of options.
*
* @param array $options
*/
public function loadConfig(array $options)
{
foreach (self::$AVAILABLE_OPTIONS as $option) {
if (isset($options[$option])) {
$method = 'set' . \ucfirst($option);
$this->$method($options[$option]);
}
}
// legacy `tabCompletion` option
if (isset($options['tabCompletion'])) {
$msg = '`tabCompletion` is deprecated; use `useTabCompletion` instead.';
@\trigger_error($msg, E_USER_DEPRECATED);
$this->setUseTabCompletion($options['tabCompletion']);
}
foreach (['commands', 'matchers', 'casters'] as $option) {
if (isset($options[$option])) {
$method = 'add' . \ucfirst($option);
$this->$method($options[$option]);
}
}
// legacy `tabCompletionMatchers` option
if (isset($options['tabCompletionMatchers'])) {
$msg = '`tabCompletionMatchers` is deprecated; use `matchers` instead.';
@\trigger_error($msg, E_USER_DEPRECATED);
$this->addMatchers($options['tabCompletionMatchers']);
}
}
/**
* Load a configuration file (default: `$HOME/.config/psysh/config.php`).
*
* This configuration instance will be available to the config file as $config.
* The config file may directly manipulate the configuration, or may return
* an array of options which will be merged with the current configuration.
*
* @throws \InvalidArgumentException if the config file returns a non-array result
*
* @param string $file
*/
public function loadConfigFile($file)
{
$__psysh_config_file__ = $file;
$load = function ($config) use ($__psysh_config_file__) {
$result = require $__psysh_config_file__;
if ($result !== 1) {
return $result;
}
};
$result = $load($this);
if (!empty($result)) {
if (\is_array($result)) {
$this->loadConfig($result);
} else {
throw new \InvalidArgumentException('Psy Shell configuration must return an array of options');
}
}
}
/**
* Set files to be included by default at the start of each shell session.
*
* @param array $includes
*/
public function setDefaultIncludes(array $includes = [])
{
$this->defaultIncludes = $includes;
}
/**
* Get files to be included by default at the start of each shell session.
*
* @return array
*/
public function getDefaultIncludes()
{
return $this->defaultIncludes ?: [];
}
/**
* Set the shell's config directory location.
*
* @param string $dir
*/
public function setConfigDir($dir)
{
$this->configDir = (string) $dir;
}
/**
* Get the current configuration directory, if any is explicitly set.
*
* @return string
*/
public function getConfigDir()
{
return $this->configDir;
}
/**
* Set the shell's data directory location.
*
* @param string $dir
*/
public function setDataDir($dir)
{
$this->dataDir = (string) $dir;
}
/**
* Get the current data directory, if any is explicitly set.
*
* @return string
*/
public function getDataDir()
{
return $this->dataDir;
}
/**
* Set the shell's temporary directory location.
*
* @param string $dir
*/
public function setRuntimeDir($dir)
{
$this->runtimeDir = (string) $dir;
}
/**
* Get the shell's temporary directory location.
*
* Defaults to `/psysh` inside the system's temp dir unless explicitly
* overridden.
*
* @return string
*/
public function getRuntimeDir()
{
if (!isset($this->runtimeDir)) {
$this->runtimeDir = ConfigPaths::getRuntimeDir();
}
if (!\is_dir($this->runtimeDir)) {
\mkdir($this->runtimeDir, 0700, true);
}
return $this->runtimeDir;
}
/**
* Set the readline history file path.
*
* @param string $file
*/
public function setHistoryFile($file)
{
$this->historyFile = ConfigPaths::touchFileWithMkdir($file);
}
/**
* Get the readline history file path.
*
* Defaults to `/history` inside the shell's base config dir unless
* explicitly overridden.
*
* @return string
*/
public function getHistoryFile()
{
if (isset($this->historyFile)) {
return $this->historyFile;
}
$files = ConfigPaths::getConfigFiles(['psysh_history', 'history'], $this->configDir);
if (!empty($files)) {
if ($this->warnOnMultipleConfigs && \count($files) > 1) {
$msg = \sprintf('Multiple history files found: %s. Using %s', \implode($files, ', '), $files[0]);
\trigger_error($msg, E_USER_NOTICE);
}
$this->setHistoryFile($files[0]);
} else {
// fallback: create our own history file
$dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
$this->setHistoryFile($dir . '/psysh_history');
}
return $this->historyFile;
}
/**
* Set the readline max history size.
*
* @param int $value
*/
public function setHistorySize($value)
{
$this->historySize = (int) $value;
}
/**
* Get the readline max history size.
*
* @return int
*/
public function getHistorySize()
{
return $this->historySize;
}
/**
* Sets whether readline erases old duplicate history entries.
*
* @param bool $value
*/
public function setEraseDuplicates($value)
{
$this->eraseDuplicates = (bool) $value;
}
/**
* Get whether readline erases old duplicate history entries.
*
* @return bool
*/
public function getEraseDuplicates()
{
return $this->eraseDuplicates;
}
/**
* Get a temporary file of type $type for process $pid.
*
* The file will be created inside the current temporary directory.
*
* @see self::getRuntimeDir
*
* @param string $type
* @param int $pid
*
* @return string Temporary file name
*/
public function getTempFile($type, $pid)
{
return \tempnam($this->getRuntimeDir(), $type . '_' . $pid . '_');
}
/**
* Get a filename suitable for a FIFO pipe of $type for process $pid.
*
* The pipe will be created inside the current temporary directory.
*
* @param string $type
* @param int $pid
*
* @return string Pipe name
*/
public function getPipe($type, $pid)
{
return \sprintf('%s/%s_%s', $this->getRuntimeDir(), $type, $pid);
}
/**
* Check whether this PHP instance has Readline available.
*
* @return bool True if Readline is available
*/
public function hasReadline()
{
return $this->hasReadline;
}
/**
* Enable or disable Readline usage.
*
* @param bool $useReadline
*/
public function setUseReadline($useReadline)
{
$this->useReadline = (bool) $useReadline;
}
/**
* Check whether to use Readline.
*
* If `setUseReadline` as been set to true, but Readline is not actually
* available, this will return false.
*
* @return bool True if the current Shell should use Readline
*/
public function useReadline()
{
return isset($this->useReadline) ? ($this->hasReadline && $this->useReadline) : $this->hasReadline;
}
/**
* Set the Psy Shell readline service.
*
* @param Readline $readline
*/
public function setReadline(Readline $readline)
{
$this->readline = $readline;
}
/**
* Get the Psy Shell readline service.
*
* By default, this service uses (in order of preference):
*
* * GNU Readline
* * Libedit
* * A transient array-based readline emulation.
*
* @return Readline
*/
public function getReadline()
{
if (!isset($this->readline)) {
$className = $this->getReadlineClass();
$this->readline = new $className(
$this->getHistoryFile(),
$this->getHistorySize(),
$this->getEraseDuplicates()
);
}
return $this->readline;
}
/**
* Get the appropriate Readline implementation class name.
*
* @see self::getReadline
*
* @return string
*/
private function getReadlineClass()
{
if ($this->useReadline()) {
if (GNUReadline::isSupported()) {
return 'Psy\Readline\GNUReadline';
} elseif (Libedit::isSupported()) {
return 'Psy\Readline\Libedit';
} elseif (HoaConsole::isSupported()) {
return 'Psy\Readline\HoaConsole';
}
}
return 'Psy\Readline\Transient';
}
/**
* Enable or disable bracketed paste.
*
* Note that this only works with readline (not libedit) integration for now.
*
* @param bool $useBracketedPaste
*/
public function setUseBracketedPaste($useBracketedPaste)
{
$this->useBracketedPaste = (bool) $useBracketedPaste;
}
/**
* Check whether to use bracketed paste with readline.
*
* When this works, it's magical. Tabs in pastes don't try to autcomplete.
* Newlines in paste don't execute code until you get to the end. It makes
* readline act like you'd expect when pasting.
*
* But it often (usually?) does not work. And when it doesn't, it just spews
* escape codes all over the place and generally makes things ugly :(
*
* If `useBracketedPaste` has been set to true, but the current readline
* implementation is anything besides GNU readline, this will return false.
*
* @return bool True if the shell should use bracketed paste
*/
public function useBracketedPaste()
{
// For now, only the GNU readline implementation supports bracketed paste.
$supported = ($this->getReadlineClass() === 'Psy\Readline\GNUReadline');
return $supported && $this->useBracketedPaste;
// @todo mebbe turn this on by default some day?
// return isset($this->useBracketedPaste) ? ($supported && $this->useBracketedPaste) : $supported;
}
/**
* Check whether this PHP instance has Pcntl available.
*
* @return bool True if Pcntl is available
*/
public function hasPcntl()
{
return $this->hasPcntl;
}
/**
* Enable or disable Pcntl usage.
*
* @param bool $usePcntl
*/
public function setUsePcntl($usePcntl)
{
$this->usePcntl = (bool) $usePcntl;
}
/**
* Check whether to use Pcntl.
*
* If `setUsePcntl` has been set to true, but Pcntl is not actually
* available, this will return false.
*
* @return bool True if the current Shell should use Pcntl
*/
public function usePcntl()
{
return isset($this->usePcntl) ? ($this->hasPcntl && $this->usePcntl) : $this->hasPcntl;
}
/**
* Enable or disable strict requirement of semicolons.
*
* @see self::requireSemicolons()
*
* @param bool $requireSemicolons
*/
public function setRequireSemicolons($requireSemicolons)
{
$this->requireSemicolons = (bool) $requireSemicolons;
}
/**
* Check whether to require semicolons on all statements.
*
* By default, PsySH will automatically insert semicolons at the end of
* statements if they're missing. To strictly require semicolons, set
* `requireSemicolons` to true.
*
* @return bool
*/
public function requireSemicolons()
{
return $this->requireSemicolons;
}
/**
* Enable or disable Unicode in PsySH specific output.
*
* Note that this does not disable Unicode output in general, it just makes
* it so PsySH won't output any itself.
*
* @param bool $useUnicode
*/
public function setUseUnicode($useUnicode)
{
$this->useUnicode = (bool) $useUnicode;
}
/**
* Check whether to use Unicode in PsySH specific output.
*
* Note that this does not disable Unicode output in general, it just makes
* it so PsySH won't output any itself.
*
* @return bool
*/
public function useUnicode()
{
if (isset($this->useUnicode)) {
return $this->useUnicode;
}
// @todo detect `chsh` != 65001 on Windows and return false
return true;
}
/**
* Set the error logging level.
*
* @see self::errorLoggingLevel
*
* @param bool $errorLoggingLevel
*/
public function setErrorLoggingLevel($errorLoggingLevel)
{
$this->errorLoggingLevel = (E_ALL | E_STRICT) & $errorLoggingLevel;
}
/**
* Get the current error logging level.
*
* By default, PsySH will automatically log all errors, regardless of the
* current `error_reporting` level. Additionally, if the `error_reporting`
* level warrants, an ErrorException will be thrown.
*
* Set `errorLoggingLevel` to 0 to prevent logging non-thrown errors. Set it
* to any valid error_reporting value to log only errors which match that
* level.
*
* http://php.net/manual/en/function.error-reporting.php
*
* @return int
*/
public function errorLoggingLevel()
{
return $this->errorLoggingLevel;
}
/**
* Set a CodeCleaner service instance.
*
* @param CodeCleaner $cleaner
*/
public function setCodeCleaner(CodeCleaner $cleaner)
{
$this->cleaner = $cleaner;
}
/**
* Get a CodeCleaner service instance.
*
* If none has been explicitly defined, this will create a new instance.
*
* @return CodeCleaner
*/
public function getCodeCleaner()
{
if (!isset($this->cleaner)) {
$this->cleaner = new CodeCleaner();
}
return $this->cleaner;
}
/**
* Enable or disable tab completion.
*
* @param bool $useTabCompletion
*/
public function setUseTabCompletion($useTabCompletion)
{
$this->useTabCompletion = (bool) $useTabCompletion;
}
/**
* @deprecated Call `setUseTabCompletion` instead
*
* @param bool $useTabCompletion
*/
public function setTabCompletion($useTabCompletion)
{
$this->setUseTabCompletion($useTabCompletion);
}
/**
* Check whether to use tab completion.
*
* If `setUseTabCompletion` has been set to true, but readline is not
* actually available, this will return false.
*
* @return bool True if the current Shell should use tab completion
*/
public function useTabCompletion()
{
return isset($this->useTabCompletion) ? ($this->hasReadline && $this->useTabCompletion) : $this->hasReadline;
}
/**
* @deprecated Call `useTabCompletion` instead
*
* @return bool
*/
public function getTabCompletion()
{
return $this->useTabCompletion();
}
/**
* Set the Shell Output service.
*
* @param ShellOutput $output
*/
public function setOutput(ShellOutput $output)
{
$this->output = $output;
}
/**
* Get a Shell Output service instance.
*
* If none has been explicitly provided, this will create a new instance
* with VERBOSITY_NORMAL and the output page supplied by self::getPager
*
* @see self::getPager
*
* @return ShellOutput
*/
public function getOutput()
{
if (!isset($this->output)) {
$this->output = new ShellOutput(
OutputInterface::VERBOSITY_NORMAL,
$this->getOutputDecorated(),
null,
$this->getPager()
);
}
return $this->output;
}
/**
* Get the decoration (i.e. color) setting for the Shell Output service.
*
* @return null|bool 3-state boolean corresponding to the current color mode
*/
public function getOutputDecorated()
{
if ($this->colorMode() === self::COLOR_MODE_AUTO) {
return;
} elseif ($this->colorMode() === self::COLOR_MODE_FORCED) {
return true;
} elseif ($this->colorMode() === self::COLOR_MODE_DISABLED) {
return false;
}
}
/**
* Set the OutputPager service.
*
* If a string is supplied, a ProcOutputPager will be used which shells out
* to the specified command.
*
* @throws \InvalidArgumentException if $pager is not a string or OutputPager instance
*
* @param string|OutputPager $pager
*/
public function setPager($pager)
{
if ($pager && !\is_string($pager) && !$pager instanceof OutputPager) {
throw new \InvalidArgumentException('Unexpected pager instance');
}
$this->pager = $pager;
}
/**
* Get an OutputPager instance or a command for an external Proc pager.
*
* If no Pager has been explicitly provided, and Pcntl is available, this
* will default to `cli.pager` ini value, falling back to `which less`.
*
* @return string|OutputPager
*/
public function getPager()
{
if (!isset($this->pager) && $this->usePcntl()) {
if ($pager = \ini_get('cli.pager')) {
// use the default pager
$this->pager = $pager;
} elseif ($less = \exec('which less 2>/dev/null')) {
// check for the presence of less...
$this->pager = $less . ' -R -S -F -X';
}
}
return $this->pager;
}
/**
* Set the Shell AutoCompleter service.
*
* @param AutoCompleter $autoCompleter
*/
public function setAutoCompleter(AutoCompleter $autoCompleter)
{
$this->autoCompleter = $autoCompleter;
}
/**
* Get an AutoCompleter service instance.
*
* @return AutoCompleter
*/
public function getAutoCompleter()
{
if (!isset($this->autoCompleter)) {
$this->autoCompleter = new AutoCompleter();
}
return $this->autoCompleter;
}
/**
* @deprecated Nothing should be using this anymore
*
* @return array
*/
public function getTabCompletionMatchers()
{
return [];
}
/**
* Add tab completion matchers to the AutoCompleter.
*
* This will buffer new matchers in the event that the Shell has not yet
* been instantiated. This allows the user to specify matchers in their
* config rc file, despite the fact that their file is needed in the Shell
* constructor.
*
* @param array $matchers
*/
public function addMatchers(array $matchers)
{
$this->newMatchers = \array_merge($this->newMatchers, $matchers);
if (isset($this->shell)) {
$this->doAddMatchers();
}
}
/**
* Internal method for adding tab completion matchers. This will set any new
* matchers once a Shell is available.
*/
private function doAddMatchers()
{
if (!empty($this->newMatchers)) {
$this->shell->addMatchers($this->newMatchers);
$this->newMatchers = [];
}
}
/**
* @deprecated Use `addMatchers` instead
*
* @param array $matchers
*/
public function addTabCompletionMatchers(array $matchers)
{
$this->addMatchers($matchers);
}
/**
* Add commands to the Shell.
*
* This will buffer new commands in the event that the Shell has not yet
* been instantiated. This allows the user to specify commands in their
* config rc file, despite the fact that their file is needed in the Shell
* constructor.
*
* @param array $commands
*/
public function addCommands(array $commands)
{
$this->newCommands = \array_merge($this->newCommands, $commands);
if (isset($this->shell)) {
$this->doAddCommands();
}
}
/**
* Internal method for adding commands. This will set any new commands once
* a Shell is available.
*/
private function doAddCommands()
{
if (!empty($this->newCommands)) {
$this->shell->addCommands($this->newCommands);
$this->newCommands = [];
}
}
/**
* Set the Shell backreference and add any new commands to the Shell.
*
* @param Shell $shell
*/
public function setShell(Shell $shell)
{
$this->shell = $shell;
$this->doAddCommands();
$this->doAddMatchers();
}
/**
* Set the PHP manual database file.
*
* This file should be an SQLite database generated from the phpdoc source
* with the `bin/build_manual` script.
*
* @param string $filename
*/
public function setManualDbFile($filename)
{
$this->manualDbFile = (string) $filename;
}
/**
* Get the current PHP manual database file.
*
* @return string Default: '~/.local/share/psysh/php_manual.sqlite'
*/
public function getManualDbFile()
{
if (isset($this->manualDbFile)) {
return $this->manualDbFile;
}
$files = ConfigPaths::getDataFiles(['php_manual.sqlite'], $this->dataDir);
if (!empty($files)) {
if ($this->warnOnMultipleConfigs && \count($files) > 1) {
$msg = \sprintf('Multiple manual database files found: %s. Using %s', \implode($files, ', '), $files[0]);
\trigger_error($msg, E_USER_NOTICE);
}
return $this->manualDbFile = $files[0];
}
}
/**
* Get a PHP manual database connection.
*
* @return \PDO
*/
public function getManualDb()
{
if (!isset($this->manualDb)) {
$dbFile = $this->getManualDbFile();
if (\is_file($dbFile)) {
try {
$this->manualDb = new \PDO('sqlite:' . $dbFile);
} catch (\PDOException $e) {
if ($e->getMessage() === 'could not find driver') {
throw new RuntimeException('SQLite PDO driver not found', 0, $e);
} else {
throw $e;
}
}
}
}
return $this->manualDb;
}
/**
* Add an array of casters definitions.
*
* @param array $casters
*/
public function addCasters(array $casters)
{
$this->getPresenter()->addCasters($casters);
}
/**
* Get the Presenter service.
*
* @return Presenter
*/
public function getPresenter()
{
if (!isset($this->presenter)) {
$this->presenter = new Presenter($this->getOutput()->getFormatter(), $this->forceArrayIndexes());
}
return $this->presenter;
}
/**
* Enable or disable warnings on multiple configuration or data files.
*
* @see self::warnOnMultipleConfigs()
*
* @param bool $warnOnMultipleConfigs
*/
public function setWarnOnMultipleConfigs($warnOnMultipleConfigs)
{
$this->warnOnMultipleConfigs = (bool) $warnOnMultipleConfigs;
}
/**
* Check whether to warn on multiple configuration or data files.
*
* By default, PsySH will use the file with highest precedence, and will
* silently ignore all others. With this enabled, a warning will be emitted
* (but not an exception thrown) if multiple configuration or data files
* are found.
*
* This will default to true in a future release, but is false for now.
*
* @return bool
*/
public function warnOnMultipleConfigs()
{
return $this->warnOnMultipleConfigs;
}
/**
* Set the current color mode.
*
* @param string $colorMode
*/
public function setColorMode($colorMode)
{
$validColorModes = [
self::COLOR_MODE_AUTO,
self::COLOR_MODE_FORCED,
self::COLOR_MODE_DISABLED,
];
if (\in_array($colorMode, $validColorModes)) {
$this->colorMode = $colorMode;
} else {
throw new \InvalidArgumentException('invalid color mode: ' . $colorMode);
}
}
/**
* Get the current color mode.
*
* @return string
*/
public function colorMode()
{
return $this->colorMode;
}
/**
* Set an update checker service instance.
*
* @param Checker $checker
*/
public function setChecker(Checker $checker)
{
$this->checker = $checker;
}
/**
* Get an update checker service instance.
*
* If none has been explicitly defined, this will create a new instance.
*
* @return Checker
*/
public function getChecker()
{
if (!isset($this->checker)) {
$interval = $this->getUpdateCheck();
switch ($interval) {
case Checker::ALWAYS:
$this->checker = new GitHubChecker();
break;
case Checker::DAILY:
case Checker::WEEKLY:
case Checker::MONTHLY:
$checkFile = $this->getUpdateCheckCacheFile();
if ($checkFile === false) {
$this->checker = new NoopChecker();
} else {
$this->checker = new IntervalChecker($checkFile, $interval);
}
break;
case Checker::NEVER:
$this->checker = new NoopChecker();
break;
}
}
return $this->checker;
}
/**
* Get the current update check interval.
*
* One of 'always', 'daily', 'weekly', 'monthly' or 'never'. If none is
* explicitly set, default to 'weekly'.
*
* @return string
*/
public function getUpdateCheck()
{
return isset($this->updateCheck) ? $this->updateCheck : Checker::WEEKLY;
}
/**
* Set the update check interval.
*
* @throws \InvalidArgumentDescription if the update check interval is unknown
*
* @param string $interval
*/
public function setUpdateCheck($interval)
{
$validIntervals = [
Checker::ALWAYS,
Checker::DAILY,
Checker::WEEKLY,
Checker::MONTHLY,
Checker::NEVER,
];
if (!\in_array($interval, $validIntervals)) {
throw new \InvalidArgumentException('invalid update check interval: ' . $interval);
}
$this->updateCheck = $interval;
}
/**
* Get a cache file path for the update checker.
*
* @return string|false Return false if config file/directory is not writable
*/
public function getUpdateCheckCacheFile()
{
$dir = $this->configDir ?: ConfigPaths::getCurrentConfigDir();
return ConfigPaths::touchFileWithMkdir($dir . '/update_check.json');
}
/**
* Set the startup message.
*
* @param string $message
*/
public function setStartupMessage($message)
{
$this->startupMessage = $message;
}
/**
* Get the startup message.
*
* @return string|null
*/
public function getStartupMessage()
{
return $this->startupMessage;
}
/**
* Set the prompt.
*
* @param string $prompt
*/
public function setPrompt($prompt)
{
$this->prompt = $prompt;
}
/**
* Get the prompt.
*
* @return string
*/
public function getPrompt()
{
return $this->prompt;
}
/**
* Get the force array indexes.
*
* @return bool
*/
public function forceArrayIndexes()
{
return $this->forceArrayIndexes;
}
/**
* Set the force array indexes.
*
* @param bool $forceArrayIndexes
*/
public function setForceArrayIndexes($forceArrayIndexes)
{
$this->forceArrayIndexes = $forceArrayIndexes;
}
}
PK ! psysh/src/ExecutionClosure.phpnu Iw setClosure($__psysh__, function () use ($__psysh__) {
try {
// Restore execution scope variables
\extract($__psysh__->getScopeVariables(false));
// Buffer stdout; we'll need it later
\ob_start([$__psysh__, 'writeStdout'], 1);
// Convert all errors to exceptions
\set_error_handler([$__psysh__, 'handleError']);
// Evaluate the current code buffer
$_ = eval($__psysh__->onExecute($__psysh__->flushCode() ?: ExecutionClosure::NOOP_INPUT));
} catch (\Throwable $_e) {
// Clean up on our way out.
\restore_error_handler();
if (\ob_get_level() > 0) {
\ob_end_clean();
}
throw $_e;
} catch (\Exception $_e) {
// Clean up on our way out.
\restore_error_handler();
if (\ob_get_level() > 0) {
\ob_end_clean();
}
throw $_e;
}
// Won't be needing this anymore
\restore_error_handler();
// Flush stdout (write to shell output, plus save to magic variable)
\ob_end_flush();
// Save execution scope variables for next time
$__psysh__->setScopeVariables(\get_defined_vars());
return $_;
});
}
/**
* Set the closure instance.
*
* @param Shell $psysh
* @param \Closure $closure
*/
protected function setClosure(Shell $shell, \Closure $closure)
{
if (self::shouldBindClosure()) {
$that = $shell->getBoundObject();
if (\is_object($that)) {
$closure = $closure->bindTo($that, \get_class($that));
} else {
$closure = $closure->bindTo(null, $shell->getBoundClass());
}
}
$this->closure = $closure;
}
/**
* Go go gadget closure.
*
* @return mixed
*/
public function execute()
{
$closure = $this->closure;
return $closure();
}
/**
* Decide whether to bind the execution closure.
*
* @return bool
*/
protected static function shouldBindClosure()
{
// skip binding on HHVM < 3.5.0
// see https://github.com/facebook/hhvm/issues/1203
if (\defined('HHVM_VERSION')) {
return \version_compare(HHVM_VERSION, '3.5.0', '>=');
}
return true;
}
}
PK ! A[-N0 N0 psysh/src/functions.phpnu Iw setScopeVariables($vars);
// Show a couple of lines of call context for the debug session.
//
// @todo come up with a better way of doing this which doesn't involve injecting input :-P
if ($sh->has('whereami')) {
$sh->addInput('whereami -n2', true);
}
if (\is_string($bindTo)) {
$sh->setBoundClass($bindTo);
} elseif ($bindTo !== null) {
$sh->setBoundObject($bindTo);
}
$sh->run();
return $sh->getScopeVariables(false);
}
}
if (!\function_exists('Psy\info')) {
/**
* Get a bunch of debugging info about the current PsySH environment and
* configuration.
*
* If a Configuration param is passed, that configuration is stored and
* used for the current shell session, and no debugging info is returned.
*
* @param Configuration|null $config
*
* @return array|null
*/
function info(Configuration $config = null)
{
static $lastConfig;
if ($config !== null) {
$lastConfig = $config;
return;
}
$xdg = new Xdg();
$home = \rtrim(\str_replace('\\', '/', $xdg->getHomeDir()), '/');
$homePattern = '#^' . \preg_quote($home, '#') . '/#';
$prettyPath = function ($path) use ($homePattern) {
if (\is_string($path)) {
return \preg_replace($homePattern, '~/', $path);
} else {
return $path;
}
};
$config = $lastConfig ?: new Configuration();
$core = [
'PsySH version' => Shell::VERSION,
'PHP version' => PHP_VERSION,
'OS' => PHP_OS,
'default includes' => $config->getDefaultIncludes(),
'require semicolons' => $config->requireSemicolons(),
'error logging level' => $config->errorLoggingLevel(),
'config file' => [
'default config file' => $prettyPath($config->getConfigFile()),
'local config file' => $prettyPath($config->getLocalConfigFile()),
'PSYSH_CONFIG env' => $prettyPath(\getenv('PSYSH_CONFIG')),
],
// 'config dir' => $config->getConfigDir(),
// 'data dir' => $config->getDataDir(),
// 'runtime dir' => $config->getRuntimeDir(),
];
// Use an explicit, fresh update check here, rather than relying on whatever is in $config.
$checker = new GitHubChecker();
$updateAvailable = null;
$latest = null;
try {
$updateAvailable = !$checker->isLatest();
$latest = $checker->getLatest();
} catch (\Exception $e) {
}
$updates = [
'update available' => $updateAvailable,
'latest release version' => $latest,
'update check interval' => $config->getUpdateCheck(),
'update cache file' => $prettyPath($config->getUpdateCheckCacheFile()),
];
if ($config->hasReadline()) {
$info = \readline_info();
$readline = [
'readline available' => true,
'readline enabled' => $config->useReadline(),
'readline service' => \get_class($config->getReadline()),
];
if (isset($info['library_version'])) {
$readline['readline library'] = $info['library_version'];
}
if (isset($info['readline_name']) && $info['readline_name'] !== '') {
$readline['readline name'] = $info['readline_name'];
}
} else {
$readline = [
'readline available' => false,
];
}
$pcntl = [
'pcntl available' => \function_exists('pcntl_signal'),
'posix available' => \function_exists('posix_getpid'),
];
$disabledFuncs = \array_map('trim', \explode(',', \ini_get('disable_functions')));
if (\in_array('pcntl_signal', $disabledFuncs) || \in_array('pcntl_fork', $disabledFuncs)) {
$pcntl['pcntl disabled'] = true;
}
$history = [
'history file' => $prettyPath($config->getHistoryFile()),
'history size' => $config->getHistorySize(),
'erase duplicates' => $config->getEraseDuplicates(),
];
$docs = [
'manual db file' => $prettyPath($config->getManualDbFile()),
'sqlite available' => true,
];
try {
if ($db = $config->getManualDb()) {
if ($q = $db->query('SELECT * FROM meta;')) {
$q->setFetchMode(\PDO::FETCH_KEY_PAIR);
$meta = $q->fetchAll();
foreach ($meta as $key => $val) {
switch ($key) {
case 'built_at':
$d = new \DateTime('@' . $val);
$val = $d->format(\DateTime::RFC2822);
break;
}
$key = 'db ' . \str_replace('_', ' ', $key);
$docs[$key] = $val;
}
} else {
$docs['db schema'] = '0.1.0';
}
}
} catch (Exception\RuntimeException $e) {
if ($e->getMessage() === 'SQLite PDO driver not found') {
$docs['sqlite available'] = false;
} else {
throw $e;
}
}
$autocomplete = [
'tab completion enabled' => $config->useTabCompletion(),
'custom matchers' => \array_map('get_class', $config->getTabCompletionMatchers()),
'bracketed paste' => $config->useBracketedPaste(),
];
// Shenanigans, but totally justified.
if ($shell = Sudo::fetchProperty($config, 'shell')) {
$core['loop listeners'] = \array_map('get_class', Sudo::fetchProperty($shell, 'loopListeners'));
$core['commands'] = \array_map('get_class', $shell->all());
$autocomplete['custom matchers'] = \array_map('get_class', Sudo::fetchProperty($shell, 'matchers'));
}
// @todo Show Presenter / custom casters.
return \array_merge($core, \compact('updates', 'pcntl', 'readline', 'history', 'docs', 'autocomplete'));
}
}
if (!\function_exists('Psy\bin')) {
/**
* `psysh` command line executable.
*
* @return \Closure
*/
function bin()
{
return function () {
$usageException = null;
$input = new ArgvInput();
try {
$input->bind(new InputDefinition([
new InputOption('help', 'h', InputOption::VALUE_NONE),
new InputOption('config', 'c', InputOption::VALUE_REQUIRED),
new InputOption('version', 'v', InputOption::VALUE_NONE),
new InputOption('cwd', null, InputOption::VALUE_REQUIRED),
new InputOption('color', null, InputOption::VALUE_NONE),
new InputOption('no-color', null, InputOption::VALUE_NONE),
new InputArgument('include', InputArgument::IS_ARRAY),
]));
} catch (\RuntimeException $e) {
$usageException = $e;
}
$config = [];
// Handle --config
if ($configFile = $input->getOption('config')) {
$config['configFile'] = $configFile;
}
// Handle --color and --no-color
if ($input->getOption('color') && $input->getOption('no-color')) {
$usageException = new \RuntimeException('Using both "--color" and "--no-color" options is invalid');
} elseif ($input->getOption('color')) {
$config['colorMode'] = Configuration::COLOR_MODE_FORCED;
} elseif ($input->getOption('no-color')) {
$config['colorMode'] = Configuration::COLOR_MODE_DISABLED;
}
$shell = new Shell(new Configuration($config));
// Handle --help
if ($usageException !== null || $input->getOption('help')) {
if ($usageException !== null) {
echo $usageException->getMessage() . PHP_EOL . PHP_EOL;
}
$version = $shell->getVersion();
$name = \basename(\reset($_SERVER['argv']));
echo <<getOption('version')) {
echo $shell->getVersion() . PHP_EOL;
exit(0);
}
// Pass additional arguments to Shell as 'includes'
$shell->setIncludes($input->getArgument('include'));
try {
// And go!
$shell->run();
} catch (\Exception $e) {
echo $e->getMessage() . PHP_EOL;
// @todo this triggers the "exited unexpectedly" logic in the
// ForkingLoop, so we can't exit(1) after starting the shell...
// fix this :)
// exit(1);
}
};
}
}
PK ! O O psysh/src/Shell.phpnu Iw run();
*
* @author Justin Hileman
*/
class Shell extends Application
{
const VERSION = 'v0.9.12';
const PROMPT = '>>> ';
const BUFF_PROMPT = '... ';
const REPLAY = '--> ';
const RETVAL = '=> ';
private $config;
private $cleaner;
private $output;
private $readline;
private $inputBuffer;
private $code;
private $codeBuffer;
private $codeBufferOpen;
private $codeStack;
private $stdoutBuffer;
private $context;
private $includes;
private $loop;
private $outputWantsNewline = false;
private $prompt;
private $loopListeners;
private $autoCompleter;
private $matchers = [];
private $commandsMatcher;
private $lastExecSuccess = true;
/**
* Create a new Psy Shell.
*
* @param Configuration $config (default: null)
*/
public function __construct(Configuration $config = null)
{
$this->config = $config ?: new Configuration();
$this->cleaner = $this->config->getCodeCleaner();
$this->loop = new ExecutionLoop();
$this->context = new Context();
$this->includes = [];
$this->readline = $this->config->getReadline();
$this->inputBuffer = [];
$this->codeStack = [];
$this->stdoutBuffer = '';
$this->loopListeners = $this->getDefaultLoopListeners();
parent::__construct('Psy Shell', self::VERSION);
$this->config->setShell($this);
// Register the current shell session's config with \Psy\info
\Psy\info($this->config);
}
/**
* Check whether the first thing in a backtrace is an include call.
*
* This is used by the psysh bin to decide whether to start a shell on boot,
* or to simply autoload the library.
*/
public static function isIncluded(array $trace)
{
return isset($trace[0]['function']) &&
\in_array($trace[0]['function'], ['require', 'include', 'require_once', 'include_once']);
}
/**
* Invoke a Psy Shell from the current context.
*
* @see Psy\debug
* @deprecated will be removed in 1.0. Use \Psy\debug instead
*
* @param array $vars Scope variables from the calling context (default: array())
* @param object|string $bindTo Bound object ($this) or class (self) value for the shell
*
* @return array Scope variables from the debugger session
*/
public static function debug(array $vars = [], $bindTo = null)
{
return \Psy\debug($vars, $bindTo);
}
/**
* Adds a command object.
*
* {@inheritdoc}
*
* @param BaseCommand $command A Symfony Console Command object
*
* @return BaseCommand The registered command
*/
public function add(BaseCommand $command)
{
if ($ret = parent::add($command)) {
if ($ret instanceof ContextAware) {
$ret->setContext($this->context);
}
if ($ret instanceof PresenterAware) {
$ret->setPresenter($this->config->getPresenter());
}
if (isset($this->commandsMatcher)) {
$this->commandsMatcher->setCommands($this->all());
}
}
return $ret;
}
/**
* 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.'),
]);
}
/**
* Gets the default commands that should always be available.
*
* @return array An array of default Command instances
*/
protected function getDefaultCommands()
{
$sudo = new Command\SudoCommand();
$sudo->setReadline($this->readline);
$hist = new Command\HistoryCommand();
$hist->setReadline($this->readline);
return [
new Command\HelpCommand(),
new Command\ListCommand(),
new Command\DumpCommand(),
new Command\DocCommand(),
new Command\ShowCommand($this->config->colorMode()),
new Command\WtfCommand($this->config->colorMode()),
new Command\WhereamiCommand($this->config->colorMode()),
new Command\ThrowUpCommand(),
new Command\TimeitCommand(),
new Command\TraceCommand(),
new Command\BufferCommand(),
new Command\ClearCommand(),
new Command\EditCommand($this->config->getRuntimeDir()),
// new Command\PsyVersionCommand(),
$sudo,
$hist,
new Command\ExitCommand(),
];
}
/**
* @return array
*/
protected function getDefaultMatchers()
{
// Store the Commands Matcher for later. If more commands are added,
// we'll update the Commands Matcher too.
$this->commandsMatcher = new Matcher\CommandsMatcher($this->all());
return [
$this->commandsMatcher,
new Matcher\KeywordsMatcher(),
new Matcher\VariablesMatcher(),
new Matcher\ConstantsMatcher(),
new Matcher\FunctionsMatcher(),
new Matcher\ClassNamesMatcher(),
new Matcher\ClassMethodsMatcher(),
new Matcher\ClassAttributesMatcher(),
new Matcher\ObjectMethodsMatcher(),
new Matcher\ObjectAttributesMatcher(),
new Matcher\ClassMethodDefaultParametersMatcher(),
new Matcher\ObjectMethodDefaultParametersMatcher(),
new Matcher\FunctionDefaultParametersMatcher(),
];
}
/**
* @deprecated Nothing should use this anymore
*/
protected function getTabCompletionMatchers()
{
@\trigger_error('getTabCompletionMatchers is no longer used', E_USER_DEPRECATED);
}
/**
* Gets the default command loop listeners.
*
* @return array An array of Execution Loop Listener instances
*/
protected function getDefaultLoopListeners()
{
$listeners = [];
if (ProcessForker::isSupported() && $this->config->usePcntl()) {
$listeners[] = new ProcessForker();
}
if (RunkitReloader::isSupported()) {
$listeners[] = new RunkitReloader();
}
return $listeners;
}
/**
* Add tab completion matchers.
*
* @param array $matchers
*/
public function addMatchers(array $matchers)
{
$this->matchers = \array_merge($this->matchers, $matchers);
if (isset($this->autoCompleter)) {
$this->addMatchersToAutoCompleter($matchers);
}
}
/**
* @deprecated Call `addMatchers` instead
*
* @param array $matchers
*/
public function addTabCompletionMatchers(array $matchers)
{
$this->addMatchers($matchers);
}
/**
* Set the Shell output.
*
* @param OutputInterface $output
*/
public function setOutput(OutputInterface $output)
{
$this->output = $output;
}
/**
* Runs the current application.
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return int 0 if everything went fine, or an error code
*/
public function run(InputInterface $input = null, OutputInterface $output = null)
{
$this->initializeTabCompletion();
if ($input === null && !isset($_SERVER['argv'])) {
$input = new ArgvInput([]);
}
if ($output === null) {
$output = $this->config->getOutput();
}
try {
return parent::run($input, $output);
} catch (\Exception $e) {
$this->writeException($e);
}
return 1;
}
/**
* Runs the current application.
*
* @throws Exception if thrown via the `throw-up` command
*
* @param InputInterface $input An Input instance
* @param OutputInterface $output An Output instance
*
* @return int 0 if everything went fine, or an error code
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
$this->setOutput($output);
$this->resetCodeBuffer();
$this->setAutoExit(false);
$this->setCatchExceptions(false);
$this->readline->readHistory();
$this->output->writeln($this->getHeader());
$this->writeVersionInfo();
$this->writeStartupMessage();
try {
$this->beforeRun();
$this->loop->run($this);
$this->afterRun();
} catch (ThrowUpException $e) {
throw $e->getPrevious();
} catch (BreakException $e) {
// The ProcessForker throws a BreakException to finish the main thread.
return;
}
}
/**
* Read user input.
*
* This will continue fetching user input until the code buffer contains
* valid code.
*
* @throws BreakException if user hits Ctrl+D
*/
public function getInput()
{
$this->codeBufferOpen = false;
do {
// reset output verbosity (in case it was altered by a subcommand)
$this->output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
$input = $this->readline();
/*
* Handle Ctrl+D. It behaves differently in different cases:
*
* 1) In an expression, like a function or "if" block, clear the input buffer
* 2) At top-level session, behave like the exit command
*/
if ($input === false) {
$this->output->writeln('');
if ($this->hasCode()) {
$this->resetCodeBuffer();
} else {
throw new BreakException('Ctrl+D');
}
}
// handle empty input
if (\trim($input) === '' && !$this->codeBufferOpen) {
continue;
}
$input = $this->onInput($input);
// If the input isn't in an open string or comment, check for commands to run.
if ($this->hasCommand($input) && !$this->inputInOpenStringOrComment($input)) {
$this->addHistory($input);
$this->runCommand($input);
continue;
}
$this->addCode($input);
} while (!$this->hasValidCode());
}
/**
* Check whether the code buffer (plus current input) is in an open string or comment.
*
* @param string $input current line of input
*
* @return bool true if the input is in an open string or comment
*/
private function inputInOpenStringOrComment($input)
{
if (!$this->hasCode()) {
return;
}
$code = $this->codeBuffer;
\array_push($code, $input);
$tokens = @\token_get_all('loopListeners as $listener) {
$listener->beforeRun($this);
}
}
/**
* Run execution loop listeners at the start of each loop.
*/
public function beforeLoop()
{
foreach ($this->loopListeners as $listener) {
$listener->beforeLoop($this);
}
}
/**
* Run execution loop listeners on user input.
*
* @param string $input
*
* @return string
*/
public function onInput($input)
{
foreach ($this->loopListeners as $listeners) {
if (($return = $listeners->onInput($this, $input)) !== null) {
$input = $return;
}
}
return $input;
}
/**
* Run execution loop listeners on code to be executed.
*
* @param string $code
*
* @return string
*/
public function onExecute($code)
{
foreach ($this->loopListeners as $listener) {
if (($return = $listener->onExecute($this, $code)) !== null) {
$code = $return;
}
}
return $code;
}
/**
* Run execution loop listeners after each loop.
*/
public function afterLoop()
{
foreach ($this->loopListeners as $listener) {
$listener->afterLoop($this);
}
}
/**
* Run execution loop listers after the shell session.
*/
protected function afterRun()
{
foreach ($this->loopListeners as $listener) {
$listener->afterRun($this);
}
}
/**
* Set the variables currently in scope.
*
* @param array $vars
*/
public function setScopeVariables(array $vars)
{
$this->context->setAll($vars);
}
/**
* Return the set of variables currently in scope.
*
* @param bool $includeBoundObject Pass false to exclude 'this'. If you're
* passing the scope variables to `extract`
* in PHP 7.1+, you _must_ exclude 'this'
*
* @return array Associative array of scope variables
*/
public function getScopeVariables($includeBoundObject = true)
{
$vars = $this->context->getAll();
if (!$includeBoundObject) {
unset($vars['this']);
}
return $vars;
}
/**
* Return the set of magic variables currently in scope.
*
* @param bool $includeBoundObject Pass false to exclude 'this'. If you're
* passing the scope variables to `extract`
* in PHP 7.1+, you _must_ exclude 'this'
*
* @return array Associative array of magic scope variables
*/
public function getSpecialScopeVariables($includeBoundObject = true)
{
$vars = $this->context->getSpecialVariables();
if (!$includeBoundObject) {
unset($vars['this']);
}
return $vars;
}
/**
* Return the set of variables currently in scope which differ from the
* values passed as $currentVars.
*
* This is used inside the Execution Loop Closure to pick up scope variable
* changes made by commands while the loop is running.
*
* @param array $currentVars
*
* @return array Associative array of scope variables which differ from $currentVars
*/
public function getScopeVariablesDiff(array $currentVars)
{
$newVars = [];
foreach ($this->getScopeVariables(false) as $key => $value) {
if (!array_key_exists($key, $currentVars) || $currentVars[$key] !== $value) {
$newVars[$key] = $value;
}
}
return $newVars;
}
/**
* Get the set of unused command-scope variable names.
*
* @return array Array of unused variable names
*/
public function getUnusedCommandScopeVariableNames()
{
return $this->context->getUnusedCommandScopeVariableNames();
}
/**
* Get the set of variable names currently in scope.
*
* @return array Array of variable names
*/
public function getScopeVariableNames()
{
return \array_keys($this->context->getAll());
}
/**
* Get a scope variable value by name.
*
* @param string $name
*
* @return mixed
*/
public function getScopeVariable($name)
{
return $this->context->get($name);
}
/**
* Set the bound object ($this variable) for the interactive shell.
*
* @param object|null $boundObject
*/
public function setBoundObject($boundObject)
{
$this->context->setBoundObject($boundObject);
}
/**
* Get the bound object ($this variable) for the interactive shell.
*
* @return object|null
*/
public function getBoundObject()
{
return $this->context->getBoundObject();
}
/**
* Set the bound class (self) for the interactive shell.
*
* @param string|null $boundClass
*/
public function setBoundClass($boundClass)
{
$this->context->setBoundClass($boundClass);
}
/**
* Get the bound class (self) for the interactive shell.
*
* @return string|null
*/
public function getBoundClass()
{
return $this->context->getBoundClass();
}
/**
* Add includes, to be parsed and executed before running the interactive shell.
*
* @param array $includes
*/
public function setIncludes(array $includes = [])
{
$this->includes = $includes;
}
/**
* Get PHP files to be parsed and executed before running the interactive shell.
*
* @return array
*/
public function getIncludes()
{
return \array_merge($this->config->getDefaultIncludes(), $this->includes);
}
/**
* Check whether this shell's code buffer contains code.
*
* @return bool True if the code buffer contains code
*/
public function hasCode()
{
return !empty($this->codeBuffer);
}
/**
* Check whether the code in this shell's code buffer is valid.
*
* If the code is valid, the code buffer should be flushed and evaluated.
*
* @return bool True if the code buffer content is valid
*/
protected function hasValidCode()
{
return !$this->codeBufferOpen && $this->code !== false;
}
/**
* Add code to the code buffer.
*
* @param string $code
* @param bool $silent
*/
public function addCode($code, $silent = false)
{
try {
// Code lines ending in \ keep the buffer open
if (\substr(\rtrim($code), -1) === '\\') {
$this->codeBufferOpen = true;
$code = \substr(\rtrim($code), 0, -1);
} else {
$this->codeBufferOpen = false;
}
$this->codeBuffer[] = $silent ? new SilentInput($code) : $code;
$this->code = $this->cleaner->clean($this->codeBuffer, $this->config->requireSemicolons());
} catch (\Exception $e) {
// Add failed code blocks to the readline history.
$this->addCodeBufferToHistory();
throw $e;
}
}
/**
* Set the code buffer.
*
* This is mostly used by `Shell::execute`. Any existing code in the input
* buffer is pushed onto a stack and will come back after this new code is
* executed.
*
* @throws \InvalidArgumentException if $code isn't a complete statement
*
* @param string $code
* @param bool $silent
*/
private function setCode($code, $silent = false)
{
if ($this->hasCode()) {
$this->codeStack[] = [$this->codeBuffer, $this->codeBufferOpen, $this->code];
}
$this->resetCodeBuffer();
try {
$this->addCode($code, $silent);
} catch (\Throwable $e) {
$this->popCodeStack();
throw $e;
} catch (\Exception $e) {
$this->popCodeStack();
throw $e;
}
if (!$this->hasValidCode()) {
$this->popCodeStack();
throw new \InvalidArgumentException('Unexpected end of input');
}
}
/**
* Get the current code buffer.
*
* This is useful for commands which manipulate the buffer.
*
* @return array
*/
public function getCodeBuffer()
{
return $this->codeBuffer;
}
/**
* Run a Psy Shell command given the user input.
*
* @throws InvalidArgumentException if the input is not a valid command
*
* @param string $input User input string
*
* @return mixed Who knows?
*/
protected function runCommand($input)
{
$command = $this->getCommand($input);
if (empty($command)) {
throw new \InvalidArgumentException('Command not found: ' . $input);
}
$input = new ShellInput(\str_replace('\\', '\\\\', \rtrim($input, " \t\n\r\0\x0B;")));
if ($input->hasParameterOption(['--help', '-h'])) {
$helpCommand = $this->get('help');
$helpCommand->setCommand($command);
return $helpCommand->run($input, $this->output);
}
return $command->run($input, $this->output);
}
/**
* Reset the current code buffer.
*
* This should be run after evaluating user input, catching exceptions, or
* on demand by commands such as BufferCommand.
*/
public function resetCodeBuffer()
{
$this->codeBuffer = [];
$this->code = false;
}
/**
* Inject input into the input buffer.
*
* This is useful for commands which want to replay history.
*
* @param string|array $input
* @param bool $silent
*/
public function addInput($input, $silent = false)
{
foreach ((array) $input as $line) {
$this->inputBuffer[] = $silent ? new SilentInput($line) : $line;
}
}
/**
* Flush the current (valid) code buffer.
*
* If the code buffer is valid, resets the code buffer and returns the
* current code.
*
* @return string PHP code buffer contents
*/
public function flushCode()
{
if ($this->hasValidCode()) {
$this->addCodeBufferToHistory();
$code = $this->code;
$this->popCodeStack();
return $code;
}
}
/**
* Reset the code buffer and restore any code pushed during `execute` calls.
*/
private function popCodeStack()
{
$this->resetCodeBuffer();
if (empty($this->codeStack)) {
return;
}
list($codeBuffer, $codeBufferOpen, $code) = \array_pop($this->codeStack);
$this->codeBuffer = $codeBuffer;
$this->codeBufferOpen = $codeBufferOpen;
$this->code = $code;
}
/**
* (Possibly) add a line to the readline history.
*
* Like Bash, if the line starts with a space character, it will be omitted
* from history. Note that an entire block multi-line code input will be
* omitted iff the first line begins with a space.
*
* Additionally, if a line is "silent", i.e. it was initially added with the
* silent flag, it will also be omitted.
*
* @param string|SilentInput $line
*/
private function addHistory($line)
{
if ($line instanceof SilentInput) {
return;
}
// Skip empty lines and lines starting with a space
if (\trim($line) !== '' && \substr($line, 0, 1) !== ' ') {
$this->readline->addHistory($line);
}
}
/**
* Filter silent input from code buffer, write the rest to readline history.
*/
private function addCodeBufferToHistory()
{
$codeBuffer = \array_filter($this->codeBuffer, function ($line) {
return !$line instanceof SilentInput;
});
$this->addHistory(\implode("\n", $codeBuffer));
}
/**
* Get the current evaluation scope namespace.
*
* @see CodeCleaner::getNamespace
*
* @return string Current code namespace
*/
public function getNamespace()
{
if ($namespace = $this->cleaner->getNamespace()) {
return \implode('\\', $namespace);
}
}
/**
* Write a string to stdout.
*
* This is used by the shell loop for rendering output from evaluated code.
*
* @param string $out
* @param int $phase Output buffering phase
*/
public function writeStdout($out, $phase = PHP_OUTPUT_HANDLER_END)
{
$isCleaning = $phase & PHP_OUTPUT_HANDLER_CLEAN;
// Incremental flush
if ($out !== '' && !$isCleaning) {
$this->output->write($out, false, OutputInterface::OUTPUT_RAW);
$this->outputWantsNewline = (\substr($out, -1) !== "\n");
$this->stdoutBuffer .= $out;
}
// Output buffering is done!
if ($phase & PHP_OUTPUT_HANDLER_END) {
// Write an extra newline if stdout didn't end with one
if ($this->outputWantsNewline) {
$this->output->writeln(\sprintf('', $this->config->useUnicode() ? '⏎' : '\\n'));
$this->outputWantsNewline = false;
}
// Save the stdout buffer as $__out
if ($this->stdoutBuffer !== '') {
$this->context->setLastStdout($this->stdoutBuffer);
$this->stdoutBuffer = '';
}
}
}
/**
* Write a return value to stdout.
*
* The return value is formatted or pretty-printed, and rendered in a
* visibly distinct manner (in this case, as cyan).
*
* @see self::presentValue
*
* @param mixed $ret
*/
public function writeReturnValue($ret)
{
$this->lastExecSuccess = true;
if ($ret instanceof NoReturnValue) {
return;
}
$this->context->setReturnValue($ret);
$ret = $this->presentValue($ret);
$indent = \str_repeat(' ', \strlen(static::RETVAL));
$this->output->writeln(static::RETVAL . \str_replace(PHP_EOL, PHP_EOL . $indent, $ret));
}
/**
* Renders a caught Exception.
*
* Exceptions are formatted according to severity. ErrorExceptions which were
* warnings or Strict errors aren't rendered as harshly as real errors.
*
* Stores $e as the last Exception in the Shell Context.
*
* @param \Exception $e An exception instance
*/
public function writeException(\Exception $e)
{
$this->lastExecSuccess = false;
$this->context->setLastException($e);
$this->output->writeln($this->formatException($e));
$this->resetCodeBuffer();
}
/**
* Check whether the last exec was successful.
*
* Returns true if a return value was logged rather than an exception.
*
* @return bool
*/
public function getLastExecSuccess()
{
return $this->lastExecSuccess;
}
/**
* Helper for formatting an exception for writeException().
*
* @todo extract this to somewhere it makes more sense
*
* @param \Exception $e
*
* @return string
*/
public function formatException(\Exception $e)
{
$message = $e->getMessage();
if (!$e instanceof PsyException) {
if ($message === '') {
$message = \get_class($e);
} else {
$message = \sprintf('%s with message \'%s\'', \get_class($e), $message);
}
}
$message = \preg_replace(
"#(\\w:)?(/\\w+)*/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code#",
"eval()'d code",
\str_replace('\\', '/', $message)
);
$message = \str_replace(" in eval()'d code", ' in Psy Shell code', $message);
$severity = ($e instanceof \ErrorException) ? $this->getSeverity($e) : 'error';
return \sprintf('<%s>%s%s>', $severity, OutputFormatter::escape($message), $severity);
}
/**
* Helper for getting an output style for the given ErrorException's level.
*
* @param \ErrorException $e
*
* @return string
*/
protected function getSeverity(\ErrorException $e)
{
$severity = $e->getSeverity();
if ($severity & \error_reporting()) {
switch ($severity) {
case E_WARNING:
case E_NOTICE:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
case E_USER_NOTICE:
case E_STRICT:
return 'warning';
default:
return 'error';
}
} else {
// Since this is below the user's reporting threshold, it's always going to be a warning.
return 'warning';
}
}
/**
* Execute code in the shell execution context.
*
* @param string $code
* @param bool $throwExceptions
*
* @return mixed
*/
public function execute($code, $throwExceptions = false)
{
$this->setCode($code, true);
$closure = new ExecutionClosure($this);
if ($throwExceptions) {
return $closure->execute();
}
try {
return $closure->execute();
} catch (\TypeError $_e) {
$this->writeException(TypeErrorException::fromTypeError($_e));
} catch (\Error $_e) {
$this->writeException(ErrorException::fromError($_e));
} catch (\Exception $_e) {
$this->writeException($_e);
}
}
/**
* Helper for throwing an ErrorException.
*
* This allows us to:
*
* set_error_handler(array($psysh, 'handleError'));
*
* Unlike ErrorException::throwException, this error handler respects the
* current error_reporting level; i.e. it logs warnings and notices, but
* doesn't throw an exception unless it's above the current error_reporting
* threshold. This should probably only be used in the inner execution loop
* of the shell, as most of the time a thrown exception is much more useful.
*
* If the error type matches the `errorLoggingLevel` config, it will be
* logged as well, regardless of the `error_reporting` level.
*
* @see \Psy\Exception\ErrorException::throwException
* @see \Psy\Shell::writeException
*
* @throws \Psy\Exception\ErrorException depending on the current error_reporting level
*
* @param int $errno Error type
* @param string $errstr Message
* @param string $errfile Filename
* @param int $errline Line number
*/
public function handleError($errno, $errstr, $errfile, $errline)
{
if ($errno & \error_reporting()) {
ErrorException::throwException($errno, $errstr, $errfile, $errline);
} elseif ($errno & $this->config->errorLoggingLevel()) {
// log it and continue...
$this->writeException(new ErrorException($errstr, 0, $errno, $errfile, $errline));
}
}
/**
* Format a value for display.
*
* @see Presenter::present
*
* @param mixed $val
*
* @return string Formatted value
*/
protected function presentValue($val)
{
return $this->config->getPresenter()->present($val);
}
/**
* Get a command (if one exists) for the current input string.
*
* @param string $input
*
* @return null|BaseCommand
*/
protected function getCommand($input)
{
$input = new StringInput($input);
if ($name = $input->getFirstArgument()) {
return $this->get($name);
}
}
/**
* Check whether a command is set for the current input string.
*
* @param string $input
*
* @return bool True if the shell has a command for the given input
*/
protected function hasCommand($input)
{
if (\preg_match('/([^\s]+?)(?:\s|$)/A', \ltrim($input), $match)) {
return $this->has($match[1]);
}
return false;
}
/**
* Get the current input prompt.
*
* @return string
*/
protected function getPrompt()
{
if ($this->hasCode()) {
return static::BUFF_PROMPT;
}
return $this->config->getPrompt() ?: static::PROMPT;
}
/**
* Read a line of user input.
*
* This will return a line from the input buffer (if any exist). Otherwise,
* it will ask the user for input.
*
* If readline is enabled, this delegates to readline. Otherwise, it's an
* ugly `fgets` call.
*
* @return string One line of user input
*/
protected function readline()
{
if (!empty($this->inputBuffer)) {
$line = \array_shift($this->inputBuffer);
if (!$line instanceof SilentInput) {
$this->output->writeln(\sprintf('', static::REPLAY, OutputFormatter::escape($line)));
}
return $line;
}
if ($bracketedPaste = $this->config->useBracketedPaste()) {
\printf("\e[?2004h"); // Enable bracketed paste
}
$line = $this->readline->readline($this->getPrompt());
if ($bracketedPaste) {
\printf("\e[?2004l"); // ... and disable it again
}
return $line;
}
/**
* Get the shell output header.
*
* @return string
*/
protected function getHeader()
{
return \sprintf('', $this->getVersion());
}
/**
* Get the current version of Psy Shell.
*
* @return string
*/
public function getVersion()
{
$separator = $this->config->useUnicode() ? '—' : '-';
return \sprintf('Psy Shell %s (PHP %s %s %s)', self::VERSION, PHP_VERSION, $separator, PHP_SAPI);
}
/**
* Get a PHP manual database instance.
*
* @return \PDO|null
*/
public function getManualDb()
{
return $this->config->getManualDb();
}
/**
* @deprecated Tab completion is provided by the AutoCompleter service
*/
protected function autocomplete($text)
{
@\trigger_error('Tab completion is provided by the AutoCompleter service', E_USER_DEPRECATED);
}
/**
* Initialize tab completion matchers.
*
* If tab completion is enabled this adds tab completion matchers to the
* auto completer and sets context if needed.
*/
protected function initializeTabCompletion()
{
if (!$this->config->useTabCompletion()) {
return;
}
$this->autoCompleter = $this->config->getAutoCompleter();
// auto completer needs shell to be linked to configuration because of
// the context aware matchers
$this->addMatchersToAutoCompleter($this->getDefaultMatchers());
$this->addMatchersToAutoCompleter($this->matchers);
$this->autoCompleter->activate();
}
/**
* Add matchers to the auto completer, setting context if needed.
*
* @param array $matchers
*/
private function addMatchersToAutoCompleter(array $matchers)
{
foreach ($matchers as $matcher) {
if ($matcher instanceof ContextAware) {
$matcher->setContext($this->context);
}
$this->autoCompleter->addMatcher($matcher);
}
}
/**
* @todo Implement self-update
* @todo Implement prompt to start update
*
* @return void|string
*/
protected function writeVersionInfo()
{
if (PHP_SAPI !== 'cli') {
return;
}
try {
$client = $this->config->getChecker();
if (!$client->isLatest()) {
$this->output->writeln(\sprintf('New version is available (current: %s, latest: %s)', self::VERSION, $client->getLatest()));
}
} catch (\InvalidArgumentException $e) {
$this->output->writeln($e->getMessage());
}
}
/**
* Write a startup message if set.
*/
protected function writeStartupMessage()
{
$message = $this->config->getStartupMessage();
if ($message !== null && $message !== '') {
$this->output->writeln($message);
}
}
}
PK ! G^/P ' psysh/src/Command/PsyVersionCommand.phpnu Iw setName('version')
->setDefinition([])
->setDescription('Show Psy Shell version.')
->setHelp('Show Psy Shell version.');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln($this->getApplication()->getVersion());
return 0;
}
}
PK ! ً[" " " psysh/src/Command/TraceCommand.phpnu Iw filter = new FilterOptions();
parent::__construct($name);
}
/**
* {@inheritdoc}
*/
protected function configure()
{
list($grep, $insensitive, $invert) = FilterOptions::getOptions();
$this
->setName('trace')
->setDefinition([
new InputOption('include-psy', 'p', InputOption::VALUE_NONE, 'Include Psy in the call stack.'),
new InputOption('num', 'n', InputOption::VALUE_REQUIRED, 'Only include NUM lines.'),
$grep,
$insensitive,
$invert,
])
->setDescription('Show the current call stack.')
->setHelp(
<<<'HELP'
Show the current call stack.
Optionally, include PsySH in the call stack by passing the --include-psy option.
e.g.
> trace -n10
> trace --include-psy
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->filter->bind($input);
$trace = $this->getBacktrace(new \Exception(), $input->getOption('num'), $input->getOption('include-psy'));
$output->page($trace, ShellOutput::NUMBER_LINES);
return 0;
}
/**
* Get a backtrace for an exception.
*
* Optionally limit the number of rows to include with $count, and exclude
* Psy from the trace.
*
* @param \Exception $e The exception with a backtrace
* @param int $count (default: PHP_INT_MAX)
* @param bool $includePsy (default: true)
*
* @return array Formatted stacktrace lines
*/
protected function getBacktrace(\Exception $e, $count = null, $includePsy = true)
{
if ($cwd = \getcwd()) {
$cwd = \rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
if ($count === null) {
$count = PHP_INT_MAX;
}
$lines = [];
$trace = $e->getTrace();
\array_unshift($trace, [
'function' => '',
'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
'args' => [],
]);
if (!$includePsy) {
for ($i = \count($trace) - 1; $i >= 0; $i--) {
$thing = isset($trace[$i]['class']) ? $trace[$i]['class'] : $trace[$i]['function'];
if (\preg_match('/\\\\?Psy\\\\/', $thing)) {
$trace = \array_slice($trace, $i + 1);
break;
}
}
}
for ($i = 0, $count = \min($count, \count($trace)); $i < $count; $i++) {
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
$function = $trace[$i]['function'];
$file = isset($trace[$i]['file']) ? $this->replaceCwd($cwd, $trace[$i]['file']) : 'n/a';
$line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
// Leave execution loop out of the `eval()'d code` lines
if (\preg_match("#/src/Execution(?:Loop)?Closure.php\(\d+\) : eval\(\)'d code$#", \str_replace('\\', '/', $file))) {
$file = "eval()'d code";
}
// Skip any lines that don't match our filter options
if (!$this->filter->match(\sprintf('%s%s%s() at %s:%s', $class, $type, $function, $file, $line))) {
continue;
}
$lines[] = \sprintf(
' %s%s%s() at %s:%s',
OutputFormatter::escape($class),
OutputFormatter::escape($type),
OutputFormatter::escape($function),
OutputFormatter::escape($file),
OutputFormatter::escape($line)
);
}
return $lines;
}
/**
* Replace the given directory from the start of a filepath.
*
* @param string $cwd
* @param string $file
*
* @return string
*/
private function replaceCwd($cwd, $file)
{
if ($cwd === false) {
return $file;
} else {
return \preg_replace('/^' . \preg_quote($cwd, '/') . '/', '', $file);
}
}
}
PK ! Њ ! psysh/src/Command/DumpCommand.phpnu Iw presenter = $presenter;
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('dump')
->setDefinition([
new CodeArgument('target', CodeArgument::REQUIRED, 'A target object or primitive to dump.'),
new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse.', 10),
new InputOption('all', 'a', InputOption::VALUE_NONE, 'Include private and protected methods and properties.'),
])
->setDescription('Dump an object or primitive.')
->setHelp(
<<<'HELP'
Dump an object or primitive.
This is like var_dump but way awesomer.
e.g.
>>> dump $_
>>> dump $someVar
>>> dump $stuff->getAll()
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$depth = $input->getOption('depth');
$target = $this->resolveCode($input->getArgument('target'));
$output->page($this->presenter->present($target, $depth, $input->getOption('all') ? Presenter::VERBOSE : 0));
if (\is_object($target)) {
$this->setCommandScopeVariables(new \ReflectionObject($target));
}
return 0;
}
/**
* @deprecated Use `resolveCode` instead
*
* @param string $name
*
* @return mixed
*/
protected function resolveTarget($name)
{
@\trigger_error('`resolveTarget` is deprecated; use `resolveCode` instead.', E_USER_DEPRECATED);
return $this->resolveCode($name);
}
}
PK ! A7
9 psysh/src/Command/ListCommand/ClassConstantEnumerator.phpnu Iw getOption('constants')) {
return;
}
$noInherit = $input->getOption('no-inherit');
$constants = $this->prepareConstants($this->getConstants($reflector, $noInherit));
if (empty($constants)) {
return;
}
$ret = [];
$ret[$this->getKindLabel($reflector)] = $constants;
return $ret;
}
/**
* Get defined constants for the given class or object Reflector.
*
* @param \Reflector $reflector
* @param bool $noInherit Exclude inherited constants
*
* @return array
*/
protected function getConstants(\Reflector $reflector, $noInherit = false)
{
$className = $reflector->getName();
$constants = [];
foreach ($reflector->getConstants() as $name => $constant) {
$constReflector = ReflectionClassConstant::create($reflector->name, $name);
if ($noInherit && $constReflector->getDeclaringClass()->getName() !== $className) {
continue;
}
$constants[$name] = $constReflector;
}
\ksort($constants, SORT_NATURAL | SORT_FLAG_CASE);
return $constants;
}
/**
* Prepare formatted constant array.
*
* @param array $constants
*
* @return array
*/
protected function prepareConstants(array $constants)
{
// My kingdom for a generator.
$ret = [];
foreach ($constants as $name => $constant) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_CONSTANT,
'value' => $this->presentRef($constant->getValue()),
];
}
}
return $ret;
}
/**
* Get a label for the particular kind of "class" represented.
*
* @param \ReflectionClass $reflector
*
* @return string
*/
protected function getKindLabel(\ReflectionClass $reflector)
{
if ($reflector->isInterface()) {
return 'Interface Constants';
} elseif (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
return 'Trait Constants';
} else {
return 'Class Constants';
}
}
}
PK ! ۥp-
4 psysh/src/Command/ListCommand/FunctionEnumerator.phpnu Iw getOption('functions')) {
return;
}
if ($input->getOption('user')) {
$label = 'User Functions';
$functions = $this->getFunctions('user');
} elseif ($input->getOption('internal')) {
$label = 'Internal Functions';
$functions = $this->getFunctions('internal');
} else {
$label = 'Functions';
$functions = $this->getFunctions();
}
$functions = $this->prepareFunctions($functions);
if (empty($functions)) {
return;
}
$ret = [];
$ret[$label] = $functions;
return $ret;
}
/**
* Get defined functions.
*
* Optionally limit functions to "user" or "internal" functions.
*
* @param null|string $type "user" or "internal" (default: both)
*
* @return array
*/
protected function getFunctions($type = null)
{
$funcs = \get_defined_functions();
if ($type) {
return $funcs[$type];
} else {
return \array_merge($funcs['internal'], $funcs['user']);
}
}
/**
* Prepare formatted function array.
*
* @param array $functions
*
* @return array
*/
protected function prepareFunctions(array $functions)
{
\natcasesort($functions);
// My kingdom for a generator.
$ret = [];
foreach ($functions as $name) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_FUNCTION,
'value' => $this->presentSignature($name),
];
}
}
return $ret;
}
}
PK ! PT 1 psysh/src/Command/ListCommand/ClassEnumerator.phpnu Iw getOption('user');
$internal = $input->getOption('internal');
$ret = [];
// only list classes, interfaces and traits if we are specifically asked
if ($input->getOption('classes')) {
$ret = \array_merge($ret, $this->filterClasses('Classes', \get_declared_classes(), $internal, $user));
}
if ($input->getOption('interfaces')) {
$ret = \array_merge($ret, $this->filterClasses('Interfaces', \get_declared_interfaces(), $internal, $user));
}
if ($input->getOption('traits')) {
$ret = \array_merge($ret, $this->filterClasses('Traits', \get_declared_traits(), $internal, $user));
}
return \array_map([$this, 'prepareClasses'], \array_filter($ret));
}
/**
* Filter a list of classes, interfaces or traits.
*
* If $internal or $user is defined, results will be limited to internal or
* user-defined classes as appropriate.
*
* @param string $key
* @param array $classes
* @param bool $internal
* @param bool $user
*
* @return array
*/
protected function filterClasses($key, $classes, $internal, $user)
{
$ret = [];
if ($internal) {
$ret['Internal ' . $key] = \array_filter($classes, function ($class) {
$refl = new \ReflectionClass($class);
return $refl->isInternal();
});
}
if ($user) {
$ret['User ' . $key] = \array_filter($classes, function ($class) {
$refl = new \ReflectionClass($class);
return !$refl->isInternal();
});
}
if (!$user && !$internal) {
$ret[$key] = $classes;
}
return $ret;
}
/**
* Prepare formatted class array.
*
* @param array $classes
*
* @return array
*/
protected function prepareClasses(array $classes)
{
\natcasesort($classes);
// My kingdom for a generator.
$ret = [];
foreach ($classes as $name) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_CLASS,
'value' => $this->presentSignature($name),
];
}
}
return $ret;
}
}
PK ! +! : psysh/src/Command/ListCommand/GlobalVariableEnumerator.phpnu Iw getOption('globals')) {
return;
}
$globals = $this->prepareGlobals($this->getGlobals());
if (empty($globals)) {
return;
}
return [
'Global Variables' => $globals,
];
}
/**
* Get defined global variables.
*
* @return array
*/
protected function getGlobals()
{
global $GLOBALS;
$names = \array_keys($GLOBALS);
\natcasesort($names);
$ret = [];
foreach ($names as $name) {
$ret[$name] = $GLOBALS[$name];
}
return $ret;
}
/**
* Prepare formatted global variable array.
*
* @param array $globals
*
* @return array
*/
protected function prepareGlobals($globals)
{
// My kingdom for a generator.
$ret = [];
foreach ($globals as $name => $value) {
if ($this->showItem($name)) {
$fname = '$' . $name;
$ret[$fname] = [
'name' => $fname,
'style' => self::IS_GLOBAL,
'value' => $this->presentRef($value),
];
}
}
return $ret;
}
}
PK ! k 4 psysh/src/Command/ListCommand/ConstantEnumerator.phpnu Iw getOption('constants')) {
return;
}
$user = $input->getOption('user');
$internal = $input->getOption('internal');
$category = $input->getOption('category');
$ret = [];
if ($user) {
$ret['User Constants'] = $this->getConstants('user');
}
if ($internal) {
$ret['Interal Constants'] = $this->getConstants('internal');
}
if ($category) {
$label = \ucfirst($category) . ' Constants';
$ret[$label] = $this->getConstants($category);
}
if (!$user && !$internal && !$category) {
$ret['Constants'] = $this->getConstants();
}
return \array_map([$this, 'prepareConstants'], \array_filter($ret));
}
/**
* Get defined constants.
*
* Optionally restrict constants to a given category, e.g. "date". If the
* category is "internal", include all non-user-defined constants.
*
* @param string $category
*
* @return array
*/
protected function getConstants($category = null)
{
if (!$category) {
return \get_defined_constants();
}
$consts = \get_defined_constants(true);
if ($category === 'internal') {
unset($consts['user']);
return \call_user_func_array('array_merge', $consts);
}
return isset($consts[$category]) ? $consts[$category] : [];
}
/**
* Prepare formatted constant array.
*
* @param array $constants
*
* @return array
*/
protected function prepareConstants(array $constants)
{
// My kingdom for a generator.
$ret = [];
$names = \array_keys($constants);
\natcasesort($names);
foreach ($names as $name) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_CONSTANT,
'value' => $this->presentRef($constants[$name]),
];
}
}
return $ret;
}
}
PK ! 4 psysh/src/Command/ListCommand/PropertyEnumerator.phpnu Iw getOption('properties')) {
return;
}
$showAll = $input->getOption('all');
$noInherit = $input->getOption('no-inherit');
$properties = $this->prepareProperties($this->getProperties($showAll, $reflector, $noInherit), $target);
if (empty($properties)) {
return;
}
$ret = [];
$ret[$this->getKindLabel($reflector)] = $properties;
return $ret;
}
/**
* Get defined properties for the given class or object Reflector.
*
* @param bool $showAll Include private and protected properties
* @param \Reflector $reflector
* @param bool $noInherit Exclude inherited properties
*
* @return array
*/
protected function getProperties($showAll, \Reflector $reflector, $noInherit = false)
{
$className = $reflector->getName();
$properties = [];
foreach ($reflector->getProperties() as $property) {
if ($noInherit && $property->getDeclaringClass()->getName() !== $className) {
continue;
}
if ($showAll || $property->isPublic()) {
$properties[$property->getName()] = $property;
}
}
\ksort($properties, SORT_NATURAL | SORT_FLAG_CASE);
return $properties;
}
/**
* Prepare formatted property array.
*
* @param array $properties
*
* @return array
*/
protected function prepareProperties(array $properties, $target = null)
{
// My kingdom for a generator.
$ret = [];
foreach ($properties as $name => $property) {
if ($this->showItem($name)) {
$fname = '$' . $name;
$ret[$fname] = [
'name' => $fname,
'style' => $this->getVisibilityStyle($property),
'value' => $this->presentValue($property, $target),
];
}
}
return $ret;
}
/**
* Get a label for the particular kind of "class" represented.
*
* @param \ReflectionClass $reflector
*
* @return string
*/
protected function getKindLabel(\ReflectionClass $reflector)
{
if ($reflector->isInterface()) {
return 'Interface Properties';
} elseif (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
return 'Trait Properties';
} else {
return 'Class Properties';
}
}
/**
* Get output style for the given property's visibility.
*
* @param \ReflectionProperty $property
*
* @return string
*/
private function getVisibilityStyle(\ReflectionProperty $property)
{
if ($property->isPublic()) {
return self::IS_PUBLIC;
} elseif ($property->isProtected()) {
return self::IS_PROTECTED;
} else {
return self::IS_PRIVATE;
}
}
/**
* Present the $target's current value for a reflection property.
*
* @param \ReflectionProperty $property
* @param mixed $target
*
* @return string
*/
protected function presentValue(\ReflectionProperty $property, $target)
{
// If $target is a class, trait or interface (try to) get the default
// value for the property.
if (!\is_object($target)) {
try {
$refl = new \ReflectionClass($target);
$props = $refl->getDefaultProperties();
if (\array_key_exists($property->name, $props)) {
$suffix = $property->isStatic() ? '' : ' ';
return $this->presentRef($props[$property->name]) . $suffix;
}
} catch (\Exception $e) {
// Well, we gave it a shot.
}
return '';
}
$property->setAccessible(true);
$value = $property->getValue($target);
return $this->presentRef($value);
}
}
PK !
4 psysh/src/Command/ListCommand/VariableEnumerator.phpnu Iw context = $context;
parent::__construct($presenter);
}
/**
* {@inheritdoc}
*/
protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null)
{
// only list variables when no Reflector is present.
if ($reflector !== null || $target !== null) {
return;
}
// only list variables if we are specifically asked
if (!$input->getOption('vars')) {
return;
}
$showAll = $input->getOption('all');
$variables = $this->prepareVariables($this->getVariables($showAll));
if (empty($variables)) {
return;
}
return [
'Variables' => $variables,
];
}
/**
* Get scope variables.
*
* @param bool $showAll Include special variables (e.g. $_)
*
* @return array
*/
protected function getVariables($showAll)
{
$scopeVars = $this->context->getAll();
\uksort($scopeVars, function ($a, $b) {
$aIndex = \array_search($a, self::$specialNames);
$bIndex = \array_search($b, self::$specialNames);
if ($aIndex !== false) {
if ($bIndex !== false) {
return $aIndex - $bIndex;
}
return 1;
}
if ($bIndex !== false) {
return -1;
}
return \strnatcasecmp($a, $b);
});
$ret = [];
foreach ($scopeVars as $name => $val) {
if (!$showAll && \in_array($name, self::$specialNames)) {
continue;
}
$ret[$name] = $val;
}
return $ret;
}
/**
* Prepare formatted variable array.
*
* @param array $variables
*
* @return array
*/
protected function prepareVariables(array $variables)
{
// My kingdom for a generator.
$ret = [];
foreach ($variables as $name => $val) {
if ($this->showItem($name)) {
$fname = '$' . $name;
$ret[$fname] = [
'name' => $fname,
'style' => \in_array($name, self::$specialNames) ? self::IS_PRIVATE : self::IS_PUBLIC,
'value' => $this->presentRef($val),
];
}
}
return $ret;
}
}
PK ! MY^ ^ 5 psysh/src/Command/ListCommand/InterfaceEnumerator.phpnu Iw getOption('interfaces')) {
return;
}
$interfaces = $this->prepareInterfaces(\get_declared_interfaces());
if (empty($interfaces)) {
return;
}
return [
'Interfaces' => $interfaces,
];
}
/**
* Prepare formatted interface array.
*
* @param array $interfaces
*
* @return array
*/
protected function prepareInterfaces(array $interfaces)
{
\natcasesort($interfaces);
// My kingdom for a generator.
$ret = [];
foreach ($interfaces as $name) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_CLASS,
'value' => $this->presentSignature($name),
];
}
}
return $ret;
}
}
PK ! qH 2 psysh/src/Command/ListCommand/MethodEnumerator.phpnu Iw getOption('methods')) {
return;
}
$showAll = $input->getOption('all');
$noInherit = $input->getOption('no-inherit');
$methods = $this->prepareMethods($this->getMethods($showAll, $reflector, $noInherit));
if (empty($methods)) {
return;
}
$ret = [];
$ret[$this->getKindLabel($reflector)] = $methods;
return $ret;
}
/**
* Get defined methods for the given class or object Reflector.
*
* @param bool $showAll Include private and protected methods
* @param \Reflector $reflector
* @param bool $noInherit Exclude inherited methods
*
* @return array
*/
protected function getMethods($showAll, \Reflector $reflector, $noInherit = false)
{
$className = $reflector->getName();
$methods = [];
foreach ($reflector->getMethods() as $name => $method) {
if ($noInherit && $method->getDeclaringClass()->getName() !== $className) {
continue;
}
if ($showAll || $method->isPublic()) {
$methods[$method->getName()] = $method;
}
}
\ksort($methods, SORT_NATURAL | SORT_FLAG_CASE);
return $methods;
}
/**
* Prepare formatted method array.
*
* @param array $methods
*
* @return array
*/
protected function prepareMethods(array $methods)
{
// My kingdom for a generator.
$ret = [];
foreach ($methods as $name => $method) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => $this->getVisibilityStyle($method),
'value' => $this->presentSignature($method),
];
}
}
return $ret;
}
/**
* Get a label for the particular kind of "class" represented.
*
* @param \ReflectionClass $reflector
*
* @return string
*/
protected function getKindLabel(\ReflectionClass $reflector)
{
if ($reflector->isInterface()) {
return 'Interface Methods';
} elseif (\method_exists($reflector, 'isTrait') && $reflector->isTrait()) {
return 'Trait Methods';
} else {
return 'Class Methods';
}
}
/**
* Get output style for the given method's visibility.
*
* @param \ReflectionMethod $method
*
* @return string
*/
private function getVisibilityStyle(\ReflectionMethod $method)
{
if ($method->isPublic()) {
return self::IS_PUBLIC;
} elseif ($method->isProtected()) {
return self::IS_PROTECTED;
} else {
return self::IS_PRIVATE;
}
}
}
PK ! . 1 psysh/src/Command/ListCommand/TraitEnumerator.phpnu Iw getOption('traits')) {
return;
}
$traits = $this->prepareTraits(\get_declared_traits());
if (empty($traits)) {
return;
}
return [
'Traits' => $traits,
];
}
/**
* Prepare formatted trait array.
*
* @param array $traits
*
* @return array
*/
protected function prepareTraits(array $traits)
{
\natcasesort($traits);
// My kingdom for a generator.
$ret = [];
foreach ($traits as $name) {
if ($this->showItem($name)) {
$ret[$name] = [
'name' => $name,
'style' => self::IS_CLASS,
'value' => $this->presentSignature($name),
];
}
}
return $ret;
}
}
PK ! `v
, psysh/src/Command/ListCommand/Enumerator.phpnu Iw filter = new FilterOptions();
$this->presenter = $presenter;
}
/**
* Return a list of categorized things with the given input options and target.
*
* @param InputInterface $input
* @param \Reflector $reflector
* @param mixed $target
*
* @return array
*/
public function enumerate(InputInterface $input, \Reflector $reflector = null, $target = null)
{
$this->filter->bind($input);
return $this->listItems($input, $reflector, $target);
}
/**
* Enumerate specific items with the given input options and target.
*
* Implementing classes should return an array of arrays:
*
* [
* 'Constants' => [
* 'FOO' => [
* 'name' => 'FOO',
* 'style' => 'public',
* 'value' => '123',
* ],
* ],
* ]
*
* @param InputInterface $input
* @param \Reflector $reflector
* @param mixed $target
*
* @return array
*/
abstract protected function listItems(InputInterface $input, \Reflector $reflector = null, $target = null);
protected function showItem($name)
{
return $this->filter->match($name);
}
protected function presentRef($value)
{
return $this->presenter->presentRef($value);
}
protected function presentSignature($target)
{
// This might get weird if the signature is actually for a reflector. Hrm.
if (!$target instanceof \Reflector) {
$target = Mirror::get($target);
}
return SignatureFormatter::format($target);
}
}
PK ! W[< < ! psysh/src/Command/ExitCommand.phpnu Iw setName('exit')
->setAliases(['quit', 'q'])
->setDefinition([])
->setDescription('End the current session and return to caller.')
->setHelp(
<<<'HELP'
End the current session and return to caller.
e.g.
>>> exit
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
throw new BreakException('Goodbye');
}
}
PK ! ӕ psysh/src/Command/DocCommand.phpnu Iw setName('doc')
->setAliases(['rtfm', 'man'])
->setDefinition([
new CodeArgument('target', CodeArgument::REQUIRED, 'Function, class, instance, constant, method or property to document.'),
])
->setDescription('Read the documentation for an object, class, constant, method or property.')
->setHelp(
<<>>> doc preg_replace
>>> doc Psy\Shell
>>> doc Psy\Shell::debug
>>> \$s = new Psy\Shell
>>> doc \$s->run
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$value = $input->getArgument('target');
if (ReflectionLanguageConstruct::isLanguageConstruct($value)) {
$reflector = new ReflectionLanguageConstruct($value);
$doc = $this->getManualDocById($value);
} else {
list($target, $reflector) = $this->getTargetAndReflector($value);
$doc = $this->getManualDoc($reflector) ?: DocblockFormatter::format($reflector);
}
$db = $this->getApplication()->getManualDb();
$output->page(function ($output) use ($reflector, $doc, $db) {
$output->writeln(SignatureFormatter::format($reflector));
$output->writeln('');
if (empty($doc) && !$db) {
$output->writeln('PHP manual not found');
$output->writeln(' To document core PHP functionality, download the PHP reference manual:');
$output->writeln(' https://github.com/bobthecow/psysh/wiki/PHP-manual');
} else {
$output->writeln($doc);
}
});
// Set some magic local variables
$this->setCommandScopeVariables($reflector);
return 0;
}
private function getManualDoc($reflector)
{
switch (\get_class($reflector)) {
case 'ReflectionClass':
case 'ReflectionObject':
case 'ReflectionFunction':
$id = $reflector->name;
break;
case 'ReflectionMethod':
$id = $reflector->class . '::' . $reflector->name;
break;
case 'ReflectionProperty':
$id = $reflector->class . '::$' . $reflector->name;
break;
case 'ReflectionClassConstant':
case 'Psy\Reflection\ReflectionClassConstant':
// @todo this is going to collide with ReflectionMethod ids
// someday... start running the query by id + type if the DB
// supports it.
$id = $reflector->class . '::' . $reflector->name;
break;
case 'Psy\Reflection\ReflectionConstant_':
$id = $reflector->name;
break;
default:
return false;
}
return $this->getManualDocById($id);
}
private function getManualDocById($id)
{
if ($db = $this->getApplication()->getManualDb()) {
return $db
->query(\sprintf('SELECT doc FROM php_manual WHERE id = %s', $db->quote($id)))
->fetchColumn(0);
}
}
}
PK ! 1? ? % psysh/src/Command/WhereamiCommand.phpnu Iw colorMode = $colorMode ?: Configuration::COLOR_MODE_AUTO;
$this->backtrace = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('whereami')
->setDefinition([
new InputOption('num', 'n', InputOption::VALUE_OPTIONAL, 'Number of lines before and after.', '5'),
])
->setDescription('Show where you are in the code.')
->setHelp(
<<<'HELP'
Show where you are in the code.
Optionally, include how many lines before and after you want to display.
e.g.
> whereami
> whereami -n10
HELP
);
}
/**
* Obtains the correct stack frame in the full backtrace.
*
* @return array
*/
protected function trace()
{
foreach (\array_reverse($this->backtrace) as $stackFrame) {
if ($this->isDebugCall($stackFrame)) {
return $stackFrame;
}
}
return \end($this->backtrace);
}
private static function isDebugCall(array $stackFrame)
{
$class = isset($stackFrame['class']) ? $stackFrame['class'] : null;
$function = isset($stackFrame['function']) ? $stackFrame['function'] : null;
return ($class === null && $function === 'Psy\debug') ||
($class === 'Psy\Shell' && \in_array($function, ['__construct', 'debug']));
}
/**
* Determine the file and line based on the specific backtrace.
*
* @return array
*/
protected function fileInfo()
{
$stackFrame = $this->trace();
if (\preg_match('/eval\(/', $stackFrame['file'])) {
\preg_match_all('/([^\(]+)\((\d+)/', $stackFrame['file'], $matches);
$file = $matches[1][0];
$line = (int) $matches[2][0];
} else {
$file = $stackFrame['file'];
$line = $stackFrame['line'];
}
return \compact('file', 'line');
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$info = $this->fileInfo();
$num = $input->getOption('num');
$factory = new ConsoleColorFactory($this->colorMode);
$colors = $factory->getConsoleColor();
$highlighter = new Highlighter($colors);
$contents = \file_get_contents($info['file']);
$output->startPaging();
$output->writeln('');
$output->writeln(\sprintf('From %s:%s:', $this->replaceCwd($info['file']), $info['line']));
$output->writeln('');
$output->write($highlighter->getCodeSnippet($contents, $info['line'], $num, $num), false, OutputInterface::OUTPUT_RAW);
$output->stopPaging();
return 0;
}
/**
* Replace the given directory from the start of a filepath.
*
* @param string $file
*
* @return string
*/
private function replaceCwd($file)
{
$cwd = \getcwd();
if ($cwd === false) {
return $file;
}
$cwd = \rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
return \preg_replace('/^' . \preg_quote($cwd, '/') . '/', '', $file);
}
}
PK ! z0_ $ psysh/src/Command/HistoryCommand.phpnu Iw filter = new FilterOptions();
parent::__construct($name);
}
/**
* Set the Shell's Readline service.
*
* @param Readline $readline
*/
public function setReadline(Readline $readline)
{
$this->readline = $readline;
}
/**
* {@inheritdoc}
*/
protected function configure()
{
list($grep, $insensitive, $invert) = FilterOptions::getOptions();
$this
->setName('history')
->setAliases(['hist'])
->setDefinition([
new InputOption('show', 's', InputOption::VALUE_REQUIRED, 'Show the given range of lines.'),
new InputOption('head', 'H', InputOption::VALUE_REQUIRED, 'Display the first N items.'),
new InputOption('tail', 'T', InputOption::VALUE_REQUIRED, 'Display the last N items.'),
$grep,
$insensitive,
$invert,
new InputOption('no-numbers', 'N', InputOption::VALUE_NONE, 'Omit line numbers.'),
new InputOption('save', '', InputOption::VALUE_REQUIRED, 'Save history to a file.'),
new InputOption('replay', '', InputOption::VALUE_NONE, 'Replay.'),
new InputOption('clear', '', InputOption::VALUE_NONE, 'Clear the history.'),
])
->setDescription('Show the Psy Shell history.')
->setHelp(
<<<'HELP'
Show, search, save or replay the Psy Shell history.
e.g.
>>> history --grep /[bB]acon/
>>> history --show 0..10 --replay
>>> history --clear
>>> history --tail 1000 --save somefile.txt
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->validateOnlyOne($input, ['show', 'head', 'tail']);
$this->validateOnlyOne($input, ['save', 'replay', 'clear']);
$history = $this->getHistorySlice(
$input->getOption('show'),
$input->getOption('head'),
$input->getOption('tail')
);
$highlighted = false;
$this->filter->bind($input);
if ($this->filter->hasFilter()) {
$matches = [];
$highlighted = [];
foreach ($history as $i => $line) {
if ($this->filter->match($line, $matches)) {
if (isset($matches[0])) {
$chunks = \explode($matches[0], $history[$i]);
$chunks = \array_map([__CLASS__, 'escape'], $chunks);
$glue = \sprintf('%s', self::escape($matches[0]));
$highlighted[$i] = \implode($glue, $chunks);
}
} else {
unset($history[$i]);
}
}
}
if ($save = $input->getOption('save')) {
$output->writeln(\sprintf('Saving history in %s...', $save));
\file_put_contents($save, \implode(PHP_EOL, $history) . PHP_EOL);
$output->writeln('History saved.');
} elseif ($input->getOption('replay')) {
if (!($input->getOption('show') || $input->getOption('head') || $input->getOption('tail'))) {
throw new \InvalidArgumentException('You must limit history via --head, --tail or --show before replaying');
}
$count = \count($history);
$output->writeln(\sprintf('Replaying %d line%s of history', $count, ($count !== 1) ? 's' : ''));
$this->getApplication()->addInput($history);
} elseif ($input->getOption('clear')) {
$this->clearHistory();
$output->writeln('History cleared.');
} else {
$type = $input->getOption('no-numbers') ? 0 : ShellOutput::NUMBER_LINES;
if (!$highlighted) {
$type = $type | OutputInterface::OUTPUT_RAW;
}
$output->page($highlighted ?: $history, $type);
}
return 0;
}
/**
* Extract a range from a string.
*
* @param string $range
*
* @return array [ start, end ]
*/
private function extractRange($range)
{
if (\preg_match('/^\d+$/', $range)) {
return [$range, $range + 1];
}
$matches = [];
if ($range !== '..' && \preg_match('/^(\d*)\.\.(\d*)$/', $range, $matches)) {
$start = $matches[1] ? \intval($matches[1]) : 0;
$end = $matches[2] ? \intval($matches[2]) + 1 : PHP_INT_MAX;
return [$start, $end];
}
throw new \InvalidArgumentException('Unexpected range: ' . $range);
}
/**
* Retrieve a slice of the readline history.
*
* @param string $show
* @param string $head
* @param string $tail
*
* @return array A slilce of history
*/
private function getHistorySlice($show, $head, $tail)
{
$history = $this->readline->listHistory();
// don't show the current `history` invocation
\array_pop($history);
if ($show) {
list($start, $end) = $this->extractRange($show);
$length = $end - $start;
} elseif ($head) {
if (!\preg_match('/^\d+$/', $head)) {
throw new \InvalidArgumentException('Please specify an integer argument for --head');
}
$start = 0;
$length = \intval($head);
} elseif ($tail) {
if (!\preg_match('/^\d+$/', $tail)) {
throw new \InvalidArgumentException('Please specify an integer argument for --tail');
}
$start = \count($history) - $tail;
$length = \intval($tail) + 1;
} else {
return $history;
}
return \array_slice($history, $start, $length, true);
}
/**
* Validate that only one of the given $options is set.
*
* @param InputInterface $input
* @param array $options
*/
private function validateOnlyOne(InputInterface $input, array $options)
{
$count = 0;
foreach ($options as $opt) {
if ($input->getOption($opt)) {
$count++;
}
}
if ($count > 1) {
throw new \InvalidArgumentException('Please specify only one of --' . \implode(', --', $options));
}
}
/**
* Clear the readline history.
*/
private function clearHistory()
{
$this->readline->clearHistory();
}
public static function escape($string)
{
return OutputFormatter::escape($string);
}
}
PK ! # # " psysh/src/Command/ClearCommand.phpnu Iw setName('clear')
->setDefinition([])
->setDescription('Clear the Psy Shell screen.')
->setHelp(
<<<'HELP'
Clear the Psy Shell screen.
Pro Tip: If your PHP has readline support, you should be able to use ctrl+l too!
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->write(\sprintf('%c[2J%c[0;0f', 27, 27));
return 0;
}
}
PK ! # psysh/src/Command/TimeitCommand.phpnu Iw Command took %.6f seconds to complete.';
const AVG_RESULT_MSG = 'Command took %.6f seconds on average (%.6f median; %.6f total) to complete.';
private static $start = null;
private static $times = [];
private $parser;
private $traverser;
private $printer;
/**
* {@inheritdoc}
*/
public function __construct($name = null)
{
$parserFactory = new ParserFactory();
$this->parser = $parserFactory->createParser();
$this->traverser = new NodeTraverser();
$this->traverser->addVisitor(new TimeitVisitor());
$this->printer = new Printer();
parent::__construct($name);
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('timeit')
->setDefinition([
new InputOption('num', 'n', InputOption::VALUE_REQUIRED, 'Number of iterations.'),
new CodeArgument('code', CodeArgument::REQUIRED, 'Code to execute.'),
])
->setDescription('Profiles with a timer.')
->setHelp(
<<<'HELP'
Time profiling for functions and commands.
e.g.
>>> timeit sleep(1)
>>> timeit -n1000 $closure()
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$code = $input->getArgument('code');
$num = $input->getOption('num') ?: 1;
$shell = $this->getApplication();
$instrumentedCode = $this->instrumentCode($code);
self::$times = [];
for ($i = 0; $i < $num; $i++) {
$_ = $shell->execute($instrumentedCode);
$this->ensureEndMarked();
}
$shell->writeReturnValue($_);
$times = self::$times;
self::$times = [];
if ($num === 1) {
$output->writeln(\sprintf(self::RESULT_MSG, $times[0]));
} else {
$total = \array_sum($times);
\rsort($times);
$median = $times[\round($num / 2)];
$output->writeln(\sprintf(self::AVG_RESULT_MSG, $total / $num, $median, $total));
}
return 0;
}
/**
* Internal method for marking the start of timeit execution.
*
* A static call to this method will be injected at the start of the timeit
* input code to instrument the call. We will use the saved start time to
* more accurately calculate time elapsed during execution.
*/
public static function markStart()
{
self::$start = \microtime(true);
}
/**
* Internal method for marking the end of timeit execution.
*
* A static call to this method is injected by TimeitVisitor at the end
* of the timeit input code to instrument the call.
*
* Note that this accepts an optional $ret parameter, which is used to pass
* the return value of the last statement back out of timeit. This saves us
* a bunch of code rewriting shenanigans.
*
* @param mixed $ret
*
* @return mixed it just passes $ret right back
*/
public static function markEnd($ret = null)
{
self::$times[] = \microtime(true) - self::$start;
self::$start = null;
return $ret;
}
/**
* Ensure that the end of code execution was marked.
*
* The end *should* be marked in the instrumented code, but just in case
* we'll add a fallback here.
*/
private function ensureEndMarked()
{
if (self::$start !== null) {
self::markEnd();
}
}
/**
* Instrument code for timeit execution.
*
* This inserts `markStart` and `markEnd` calls to ensure that (reasonably)
* accurate times are recorded for just the code being executed.
*
* @param string $code
*
* @return string
*/
private function instrumentCode($code)
{
return $this->printer->prettyPrint($this->traverser->traverse($this->parse($code)));
}
/**
* Lex and parse a string of code into statements.
*
* @param string $code
*
* @return array Statements
*/
private function parse($code)
{
$code = 'parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $this->parser->parse($code . ';');
}
}
}
PK ! 3 " psysh/src/Command/ParseCommand.phpnu Iw parserFactory = new ParserFactory();
$this->parsers = [];
parent::__construct($name);
}
/**
* ContextAware interface.
*
* @param Context $context
*/
public function setContext(Context $context)
{
$this->context = $context;
}
/**
* PresenterAware interface.
*
* @param Presenter $presenter
*/
public function setPresenter(Presenter $presenter)
{
$this->presenter = clone $presenter;
$this->presenter->addCasters([
'PhpParser\Node' => function (Node $node, array $a) {
$a = [
Caster::PREFIX_VIRTUAL . 'type' => $node->getType(),
Caster::PREFIX_VIRTUAL . 'attributes' => $node->getAttributes(),
];
foreach ($node->getSubNodeNames() as $name) {
$a[Caster::PREFIX_VIRTUAL . $name] = $node->$name;
}
return $a;
},
]);
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$definition = [
new CodeArgument('code', CodeArgument::REQUIRED, 'PHP code to parse.'),
new InputOption('depth', '', InputOption::VALUE_REQUIRED, 'Depth to parse.', 10),
];
if ($this->parserFactory->hasKindsSupport()) {
$msg = 'One of PhpParser\\ParserFactory constants: '
. \implode(', ', ParserFactory::getPossibleKinds())
. " (default is based on current interpreter's version).";
$defaultKind = $this->parserFactory->getDefaultKind();
$definition[] = new InputOption('kind', '', InputOption::VALUE_REQUIRED, $msg, $defaultKind);
}
$this
->setName('parse')
->setDefinition($definition)
->setDescription('Parse PHP code and show the abstract syntax tree.')
->setHelp(
<<<'HELP'
Parse PHP code and show the abstract syntax tree.
This command is used in the development of PsySH. Given a string of PHP code,
it pretty-prints the PHP Parser parse tree.
See https://github.com/nikic/PHP-Parser
It prolly won't be super useful for most of you, but it's here if you want to play.
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$code = $input->getArgument('code');
if (\strpos('', $code) === false) {
$code = 'parserFactory->hasKindsSupport() ? $input->getOption('kind') : null;
$depth = $input->getOption('depth');
$nodes = $this->parse($this->getParser($parserKind), $code);
$output->page($this->presenter->present($nodes, $depth));
$this->context->setReturnValue($nodes);
return 0;
}
/**
* Lex and parse a string of code into statements.
*
* @param Parser $parser
* @param string $code
*
* @return array Statements
*/
private function parse(Parser $parser, $code)
{
try {
return $parser->parse($code);
} catch (\PhpParser\Error $e) {
if (\strpos($e->getMessage(), 'unexpected EOF') === false) {
throw $e;
}
// If we got an unexpected EOF, let's try it again with a semicolon.
return $parser->parse($code . ';');
}
}
/**
* Get (or create) the Parser instance.
*
* @param string|null $kind One of Psy\ParserFactory constants (only for PHP parser 2.0 and above)
*
* @return Parser
*/
private function getParser($kind = null)
{
if (!\array_key_exists($kind, $this->parsers)) {
$this->parsers[$kind] = $this->parserFactory->createParser($kind);
}
return $this->parsers[$kind];
}
}
PK ! ^@% % ! psysh/src/Command/ShowCommand.phpnu Iw colorMode = $colorMode ?: Configuration::COLOR_MODE_AUTO;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('show')
->setDefinition([
new CodeArgument('target', CodeArgument::OPTIONAL, 'Function, class, instance, constant, method or property to show.'),
new InputOption('ex', null, InputOption::VALUE_OPTIONAL, 'Show last exception context. Optionally specify a stack index.', 1),
])
->setDescription('Show the code for an object, class, constant, method or property.')
->setHelp(
<<cat --ex defaults to showing the lines surrounding the location of the last
exception. Invoking it more than once travels up the exception's stack trace,
and providing a number shows the context of the given index of the trace.
e.g.
>>> show \$myObject
>>> show Psy\Shell::debug
>>> show --ex
>>> show --ex 3
HELP
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
// n.b. As far as I can tell, InputInterface doesn't want to tell me
// whether an option with an optional value was actually passed. If you
// call `$input->getOption('ex')`, it will return the default, both when
// `--ex` is specified with no value, and when `--ex` isn't specified at
// all.
//
// So we're doing something sneaky here. If we call `getOptions`, it'll
// return the default value when `--ex` is not present, and `null` if
// `--ex` is passed with no value. /shrug
$opts = $input->getOptions();
// Strict comparison to `1` (the default value) here, because `--ex 1`
// will come in as `"1"`. Now we can tell the difference between
// "no --ex present", because it's the integer 1, "--ex with no value",
// because it's `null`, and "--ex 1", because it's the string "1".
if ($opts['ex'] !== 1) {
if ($input->getArgument('target')) {
throw new \InvalidArgumentException('Too many arguments (supply either "target" or "--ex")');
}
$this->writeExceptionContext($input, $output);
return 0;
}
if ($input->getArgument('target')) {
$this->writeCodeContext($input, $output);
return 0;
}
throw new RuntimeException('Not enough arguments (missing: "target")');
}
private function writeCodeContext(InputInterface $input, OutputInterface $output)
{
list($target, $reflector) = $this->getTargetAndReflector($input->getArgument('target'));
// Set some magic local variables
$this->setCommandScopeVariables($reflector);
try {
$output->page(CodeFormatter::format($reflector, $this->colorMode), OutputInterface::OUTPUT_RAW);
} catch (RuntimeException $e) {
$output->writeln(SignatureFormatter::format($reflector));
throw $e;
}
}
private function writeExceptionContext(InputInterface $input, OutputInterface $output)
{
$exception = $this->context->getLastException();
if ($exception !== $this->lastException) {
$this->lastException = null;
$this->lastExceptionIndex = null;
}
$opts = $input->getOptions();
if ($opts['ex'] === null) {
if ($this->lastException && $this->lastExceptionIndex !== null) {
$index = $this->lastExceptionIndex + 1;
} else {
$index = 0;
}
} else {
$index = \max(0, \intval($input->getOption('ex')) - 1);
}
$trace = $exception->getTrace();
\array_unshift($trace, [
'file' => $exception->getFile(),
'line' => $exception->getLine(),
]);
if ($index >= \count($trace)) {
$index = 0;
}
$this->lastException = $exception;
$this->lastExceptionIndex = $index;
$output->writeln($this->getApplication()->formatException($exception));
$output->writeln('--');
$this->writeTraceLine($output, $trace, $index);
$this->writeTraceCodeSnippet($output, $trace, $index);
$this->setCommandScopeVariablesFromContext($trace[$index]);
}
private function writeTraceLine(OutputInterface $output, array $trace, $index)
{
$file = isset($trace[$index]['file']) ? $this->replaceCwd($trace[$index]['file']) : 'n/a';
$line = isset($trace[$index]['line']) ? $trace[$index]['line'] : 'n/a';
$output->writeln(\sprintf(
'From %s:%d at level %d of backtrace (of %d).',
OutputFormatter::escape($file),
OutputFormatter::escape($line),
$index + 1,
\count($trace)
));
}
private function replaceCwd($file)
{
if ($cwd = \getcwd()) {
$cwd = \rtrim($cwd, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
if ($cwd === false) {
return $file;
} else {
return \preg_replace('/^' . \preg_quote($cwd, '/') . '/', '', $file);
}
}
private function writeTraceCodeSnippet(OutputInterface $output, array $trace, $index)
{
if (!isset($trace[$index]['file'])) {
return;
}
$file = $trace[$index]['file'];
if ($fileAndLine = $this->extractEvalFileAndLine($file)) {
list($file, $line) = $fileAndLine;
} else {
if (!isset($trace[$index]['line'])) {
return;
}
$line = $trace[$index]['line'];
}
if (\is_file($file)) {
$code = @\file_get_contents($file);
}
if (empty($code)) {
return;
}
$output->write($this->getHighlighter()->getCodeSnippet($code, $line, 5, 5), false, OutputInterface::OUTPUT_RAW);
}
private function getHighlighter()
{
if (!$this->highlighter) {
$factory = new ConsoleColorFactory($this->colorMode);
$this->highlighter = new Highlighter($factory->getConsoleColor());
}
return $this->highlighter;
}
private function setCommandScopeVariablesFromContext(array $context)
{
$vars = [];
if (isset($context['class'])) {
$vars['__class'] = $context['class'];
if (isset($context['function'])) {
$vars['__method'] = $context['function'];
}
try {
$refl = new \ReflectionClass($context['class']);
if ($namespace = $refl->getNamespaceName()) {
$vars['__namespace'] = $namespace;
}
} catch (\Exception $e) {
// oh well
}
} elseif (isset($context['function'])) {
$vars['__function'] = $context['function'];
try {
$refl = new \ReflectionFunction($context['function']);
if ($namespace = $refl->getNamespaceName()) {
$vars['__namespace'] = $namespace;
}
} catch (\Exception $e) {
// oh well
}
}
if (isset($context['file'])) {
$file = $context['file'];
if ($fileAndLine = $this->extractEvalFileAndLine($file)) {
list($file, $line) = $fileAndLine;
} elseif (isset($context['line'])) {
$line = $context['line'];
}
if (\is_file($file)) {
$vars['__file'] = $file;
if (isset($line)) {
$vars['__line'] = $line;
}
$vars['__dir'] = \dirname($file);
}
}
$this->context->setCommandScopeVariables($vars);
}
private function extractEvalFileAndLine($file)
{
if (\preg_match('/(.*)\\((\\d+)\\) : eval\\(\\)\'d code$/', $file, $matches)) {
return [$matches[1], $matches[2]];
}
}
}
PK ! -0
! psysh/src/Command/HelpCommand.phpnu Iw setName('help')
->setAliases(['?'])
->setDefinition([
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name.', null),
])
->setDescription('Show a list of commands. Type `help [foo]` for information about [foo].')
->setHelp('My. How meta.');
}
/**
* Helper for setting a subcommand to retrieve help for.
*
* @param Command $command
*/
public function setCommand($command)
{
$this->command = $command;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if ($this->command !== null) {
// help for an individual command
$output->page($this->command->asText());
$this->command = null;
} elseif ($name = $input->getArgument('command_name')) {
// help for an individual command
$output->page($this->getApplication()->get($name)->asText());
} else {
// list available commands
$commands = $this->getApplication()->all();
$table = $this->getTable($output);
foreach ($commands as $name => $command) {
if ($name !== $command->getName()) {
continue;
}
if ($command->getAliases()) {
$aliases = \sprintf('Aliases: %s', \implode(', ', $command->getAliases()));
} else {
$aliases = '';
}
$table->addRow([
\sprintf('%s', $name),
$command->getDescription(),
$aliases,
]);
}
$output->startPaging();
if ($table instanceof TableHelper) {
$table->render($output);
} else {
$table->render();
}
$output->stopPaging();
}
return 0;
}
}
PK ! M psysh/src/Command/Command.phpnu Iw Usage:',
' ' . $this->getSynopsis(),
'',
];
if ($this->getAliases()) {
$messages[] = $this->aliasesAsText();
}
if ($this->getArguments()) {
$messages[] = $this->argumentsAsText();
}
if ($this->getOptions()) {
$messages[] = $this->optionsAsText();
}
if ($help = $this->getProcessedHelp()) {
$messages[] = 'Help:';
$messages[] = ' ' . \str_replace("\n", "\n ", $help) . "\n";
}
return \implode("\n", $messages);
}
/**
* {@inheritdoc}
*/
private function getArguments()
{
$hidden = $this->getHiddenArguments();
return \array_filter($this->getNativeDefinition()->getArguments(), function ($argument) use ($hidden) {
return !\in_array($argument->getName(), $hidden);
});
}
/**
* These arguments will be excluded from help output.
*
* @return array
*/
protected function getHiddenArguments()
{
return ['command'];
}
/**
* {@inheritdoc}
*/
private function getOptions()
{
$hidden = $this->getHiddenOptions();
return \array_filter($this->getNativeDefinition()->getOptions(), function ($option) use ($hidden) {
return !\in_array($option->getName(), $hidden);
});
}
/**
* These options will be excluded from help output.
*
* @return array
*/
protected function getHiddenOptions()
{
return ['verbose'];
}
/**
* Format command aliases as text..
*
* @return string
*/
private function aliasesAsText()
{
return 'Aliases: ' . \implode(', ', $this->getAliases()) . '' . PHP_EOL;
}
/**
* Format command arguments as text.
*
* @return string
*/
private function argumentsAsText()
{
$max = $this->getMaxWidth();
$messages = [];
$arguments = $this->getArguments();
if (!empty($arguments)) {
$messages[] = 'Arguments:';
foreach ($arguments as $argument) {
if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
$default = \sprintf(' (default: %s)', $this->formatDefaultValue($argument->getDefault()));
} else {
$default = '';
}
$description = \str_replace("\n", "\n" . \str_pad('', $max + 2, ' '), $argument->getDescription());
$messages[] = \sprintf(" %-${max}s %s%s", $argument->getName(), $description, $default);
}
$messages[] = '';
}
return \implode(PHP_EOL, $messages);
}
/**
* Format options as text.
*
* @return string
*/
private function optionsAsText()
{
$max = $this->getMaxWidth();
$messages = [];
$options = $this->getOptions();
if ($options) {
$messages[] = 'Options:';
foreach ($options as $option) {
if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
$default = \sprintf(' (default: %s)', $this->formatDefaultValue($option->getDefault()));
} else {
$default = '';
}
$multiple = $option->isArray() ? ' (multiple values allowed)' : '';
$description = \str_replace("\n", "\n" . \str_pad('', $max + 2, ' '), $option->getDescription());
$optionMax = $max - \strlen($option->getName()) - 2;
$messages[] = \sprintf(
" %s %-${optionMax}s%s%s%s",
'--' . $option->getName(),
$option->getShortcut() ? \sprintf('(-%s) ', $option->getShortcut()) : '',
$description,
$default,
$multiple
);
}
$messages[] = '';
}
return \implode(PHP_EOL, $messages);
}
/**
* Calculate the maximum padding width for a set of lines.
*
* @return int
*/
private function getMaxWidth()
{
$max = 0;
foreach ($this->getOptions() as $option) {
$nameLength = \strlen($option->getName()) + 2;
if ($option->getShortcut()) {
$nameLength += \strlen($option->getShortcut()) + 3;
}
$max = \max($max, $nameLength);
}
foreach ($this->getArguments() as $argument) {
$max = \max($max, \strlen($argument->getName()));
}
return ++$max;
}
/**
* Format an option default as text.
*
* @param mixed $default
*
* @return string
*/
private function formatDefaultValue($default)
{
if (\is_array($default) && $default === \array_values($default)) {
return \sprintf("array('%s')", \implode("', '", $default));
}
return \str_replace("\n", '', \var_export($default, true));
}
/**
* Get a Table instance.
*
* Falls back to legacy TableHelper.
*
* @return Table|TableHelper
*/
protected function getTable(OutputInterface $output)
{
if (!\class_exists('Symfony\Component\Console\Helper\Table')) {
return $this->getTableHelper();
}
$style = new TableStyle();
$style
->setVerticalBorderChar(' ')
->setHorizontalBorderChar('')
->setCrossingChar('');
$table = new Table($output);
return $table
->setRows([])
->setStyle($style);
}
/**
* Legacy fallback for getTable.
*
* @return TableHelper
*/
protected function getTableHelper()
{
$table = $this->getApplication()->getHelperSet()->get('table');
return $table
->setRows([])
->setLayout(TableHelper::LAYOUT_BORDERLESS)
->setHorizontalBorderChar('')
->setCrossingChar('');
}
}
PK ! 3;&