diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/Commands/PluginCommand.php b/Commands/PluginCommand.php index 5e4d6aa..9e3162a 100644 --- a/Commands/PluginCommand.php +++ b/Commands/PluginCommand.php @@ -2,11 +2,15 @@ namespace Terminus\Commands; +require_once __DIR__.'/../vendor/autoload.php'; + use Symfony\Component\Yaml\Yaml; use Terminus\Commands\TerminusCommand; use Terminus\Exceptions\TerminusException; use Terminus\Utils; +const DEFAULT_URL = 'http://live-terminus-plugins.pantheonsite.io/plugins.json'; + /** * Manage Terminus plugins * @@ -35,9 +39,7 @@ public function __construct(array $options = []) { */ public function install($args = array()) { if (empty($args)) { - $message = "Usage: terminus plugin install | add plugin-name-1 |"; - $message .= " [plugin-name-2 |"; - $message .= " ] ..."; + $message = "Usage: terminus plugin install plugin-name-1 [plugin-name-2] [plugin-name-3]"; $this->failure($message); } @@ -58,7 +60,6 @@ public function install($args = array()) { $message = "$plugin plugin already installed."; $this->log()->notice($message); } else { - $this->addRepository($repository); exec("cd \"$plugins_dir\" && git clone $arg", $output); foreach ($output as $message) { $this->log()->notice($message); @@ -71,13 +72,12 @@ public function install($args = array()) { $message = "No plugins found matching $arg."; $this->log()->error($message); } else { - foreach ($plugins as $plugin => $repository) { - if (is_dir($plugins_dir . $plugin)) { - $message = "$plugin plugin already installed."; + foreach ($plugins as $plugin => $item) { + if (is_dir($plugins_dir . $item['package'])) { + $message = "{$item['package']} plugin already installed."; $this->log()->notice($message); } else { - $repo = $repository . '/' . $plugin; - exec("cd \"$plugins_dir\" && git clone $repo", $output); + exec("cd \"$plugins_dir\" && git clone {$item['repo']} {$item['package']}", $output); foreach ($output as $message) { $this->log()->notice($message); } @@ -202,84 +202,32 @@ public function uninstall($args = array()) { * @alias find */ public function search($args = array()) { - if (empty($args)) { - $message = "Usage: terminus plugin search plugin-name-1"; - $message .= " [plugin-name-2] ..."; + if (empty($args) || count($args) > 1) { + $message = "Usage: terminus plugin search plugin-name"; $this->failure($message); } - $plugins = $this->searchRepositories($args); if (empty($plugins)) { $message = "No plugins were found."; $this->log()->notice($message); } else { - $message = "The following plugins were found:"; + $message = "The following plugin were found:"; $this->log()->notice($message); - foreach ($plugins as $plugin => $title) { - $this->log()->notice($title); + + $table = new \Console_Table(); + $table->setHeaders( + array('Package', 'Title', 'Description', 'Author') + ); + + foreach($plugins AS $item){ + $table->addRow(array($item['package']. ($item['installed'] ? ' ( installed )' : ''), $item['title'], trim(strip_tags($item['description'])), "{$item['creator']}".( !empty($item['creator_email']) ? " <{$item['creator_email']}>" : ""))); } - } - } - /** - * Manage repositories - * - * @param array $args A subcommand followed by a list of one - * or more repositories - * - * @subcommand repository - * @alias repo - */ - public function repository($args = array()) { - $usage = "Usage: terminus plugin repository | repo add | list | remove"; - $usage .= " "; - $usage .= " [] ..."; - if (empty($args)) { - $this->failure($usage); - } - $cmd = array_shift($args); - $valid_cmds = array('add', 'list', 'remove'); - if (!in_array($cmd, $valid_cmds)) { - $this->failure($usage); - } - switch ($cmd) { - case 'add': - if (empty($args)) { - $this->failure($usage); - } - foreach ($args as $arg) { - $this->addRepository($arg); - } - break; - case 'list': - $repositories = $this->listRepositories(); - if (empty($repositories)) { - $message = 'No plugin repositories exist.'; - $this->log()->error($message); - } else { - $repo_yml = $this->getRepositoriesPath(); - $message = "Plugin repositories are stored in $repo_yml."; - $this->log()->notice($message); - $message = "The following plugin repositories are available:"; - $this->log()->notice($message); - foreach ($repositories as $repository) { - $this->log()->notice($repository); - } - $message = "The 'terminus plugin search' command will only search in these repositories."; - $this->log()->notice($message); - } - break; - case 'remove': - if (empty($args)) { - $this->failure($usage); - } - foreach ($args as $arg) { - $this->removeRepository($arg); - } - break; + print $table->getTable(); } } + /** * Get the plugin directory * @@ -365,165 +313,6 @@ private function updatePlugin($arg) { } } - /** - * Get repositories - * - * @return array Parsed Yaml from the repositories.yml file - */ - private function getRepositories() { - $repo_yml = $this->getRepositoriesPath(); - $header = $this->getRepositoriesHeader(); - if (file_exists($repo_yml)) { - $repo_data = @file_get_contents($repo_yml); - if ($repo_data != $header) { - return Yaml::parse($repo_data); - } - } else { - $handle = fopen($repo_yml, "w"); - fwrite($handle, $header); - fclose($handle); - } - return array(); - } - - /** - * Get repositories.yml path - * - * @return string The full path to the repositories.yml file - */ - private function getRepositoriesPath() { - $plugin_dir = $this->getPluginDir(); - return $plugin_dir . 'repositories.yml'; - } - - /** - * Get repositories.yml header - * - * @return string repositories.yml header - */ - private function getRepositoriesHeader() { - return <<isValidUrl($repo)) { - $message = "$repo is not a valid URL."; - $this->failure($message); - } - $repo_exists = false; - $repositories = $this->listRepositories(); - foreach ($repositories as $repository) { - if ($repository == $repo) { - $message = "Unable to add $repo. Repository already added."; - $this->log()->error($message); - $repo_exists = true; - break; - } - } - if (!$repo_exists) { - $parts = parse_url($repo); - if (isset($parts['path']) && ($parts['path'] != '/')) { - $host = $parts['scheme'] . '://' . $parts['host']; - $path = substr($parts['path'], 1); - $repositories = $this->getRepositories(); - $repositories[$host][] = $path; - $this->saveRepositories($repositories); - } - } - } - - /** - * List repositories - * - * @return array List of fully qualified domain repository URLs - */ - private function listRepositories() { - $repo_urls = array(); - $repositories = $this->getRepositories(); - foreach ($repositories as $host => $repository) { - foreach ($repository as $path) { - $repo_urls[] = $host . '/' . $path; - } - } - return $repo_urls; - } - - /** - * Remove repository - * - * @param string $repo Repository URL - */ - private function removeRepository($repo = '') { - $exists = false; - $repositories = $this->listRepositories(); - foreach ($repositories as $repository) { - if ($repository == $repo) { - $exists = true; - break; - } - } - if (!$exists) { - $message = "Unable to remove $repo. Repository does not exist."; - $this->log()->error($message); - } else { - $parts = parse_url($repo); - $host = $parts['scheme'] . '://' . $parts['host']; - $path = substr($parts['path'], 1); - $repositories = $this->getRepositories(); - foreach ($repositories as $repo_host => $repository) { - if ($repo_host == $host) { - foreach ($repository as $key => $repo_url) { - if ($repo_url == $path) { - unset($repositories[$host][$key]); - $this->saveRepositories($repositories, 'remove'); - break; - } - } - break; - } - } - } - } - - /** - * Save repositories - * - * @param array $repos A list of plugin repositories - */ - private function saveRepositories($repos = array(), $op = 'add') { - $repo_yml = $this->getRepositoriesPath(); - $header = $this->getRepositoriesHeader(); - $repo_data = "$header\n" . Yaml::dump($repos); - try { - $handle = fopen($repo_yml, "w"); - fwrite($handle, $repo_data); - fclose($handle); - } catch (Exception $e) { - $messages = array(); - $messages[] = "Unable to $op plugin repository."; - $messages[] = $e->getMessage(); - $message = implode("\n", $messages); - $this->failure($message); - } - if ($op == 'add') { - $oped = 'added'; - } else { - $oped = 'removed'; - } - $message = "Plugin repository was $oped successfully."; - $this->log()->notice($message); - } - /** * Search repositories * @@ -531,50 +320,22 @@ private function saveRepositories($repos = array(), $op = 'add') { * @return array List of plugin names found */ private function searchRepositories($args = array()) { - $titles = array(); - $plugins = array(); - $repositories = $this->listRepositories(); - foreach ($repositories as $repository) { - foreach ($args as $arg) { - $url = $repository . '/' . $arg; - if ($this->isValidUrl($url)) { - if ($this->isValidPlugin($repository, $arg)) { - $plugins[$arg] = $repository; - } - } else { - $parts = @parse_url($repository); - if (isset($parts['host'])) { - $host = $parts['host']; - switch ($host) { - case 'bitbucket.com': - // TODO: Add BitBucket parsing logic - break; - case 'github.com': - $repo_data = @file_get_contents($repository . '?tab=repositories'); - if (!empty($repo_data)) { - $path = $parts['path']; - $pattern = '|' . $path . '/(.*)".*codeRepository|U'; - preg_match_all($pattern, $repo_data, $matches); - if (isset($matches[1])) { - foreach ($matches[1] as $match) { - if ($title = $this->isValidPlugin($repository, $match)) { - $titles["$repository/$match"] = $title; - } - } - foreach ($titles as $repo => $title) { - if ((stripos($repo, $arg) !== false) || (stripos($title, $arg) !== false)) { - $plugins[$repo] = $title; - } - } - } - } - break; - default: - } - } - } - } + $plugins_dir = $this->getPluginDir(); + + $results = file_get_contents(DEFAULT_URL . '?package='.$args[0]); + + $results = json_decode($results, true); + + $output = array_column($results, 'package'); + $plugin_search = preg_grep("/{$args[0]}/", $output); + $keys = array_keys($results); + foreach($plugin_search as $index => $package){ + $plugin_id = $keys[$index]; + $item = $results[$plugin_id]; + $item['installed'] = is_dir($plugins_dir . $item['package']); + $plugins[] = $item; } + return $plugins; } @@ -602,10 +363,7 @@ private function isValidPlugin($repository, $plugin) { preg_match('|(.*)|', $plugin_data, $match); if (isset($match[1])) { $title = $match[1]; - if (stripos($title, 'terminus') && stripos($title, 'plugin')) { - return $title; - } - return ''; + return $title; } return ''; } diff --git a/composer.json b/composer.json index 144f6d3..b4501a5 100644 --- a/composer.json +++ b/composer.json @@ -4,6 +4,7 @@ "homepage": "https://github.com/uberhacker/tpm", "license": "MIT", "require": { - "php": ">=5.4" - }, + "php": ">=5.4", + "pear/console_table": "^1.3" + } } diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..4a801e6 --- /dev/null +++ b/composer.lock @@ -0,0 +1,76 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "fa2e76dd559effe1bacbae67a50e141f", + "content-hash": "e59708f6386effa97a6a26da99273b51", + "packages": [ + { + "name": "pear/console_table", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/pear/Console_Table.git", + "reference": "64100b9ee81852f4fa17823e55d0b385a544f976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Console_Table/zipball/64100b9ee81852f4fa17823e55d0b385a544f976", + "reference": "64100b9ee81852f4fa17823e55d0b385a544f976", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "pear/Console_Color2": ">=0.1.2" + }, + "type": "library", + "autoload": { + "classmap": [ + "Table.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jan Schneider", + "homepage": "http://pear.php.net/user/yunosh" + }, + { + "name": "Tal Peer", + "homepage": "http://pear.php.net/user/tal" + }, + { + "name": "Xavier Noguer", + "homepage": "http://pear.php.net/user/xnoguer" + }, + { + "name": "Richard Heyes", + "homepage": "http://pear.php.net/user/richard" + } + ], + "description": "Library that makes it easy to build console style tables.", + "homepage": "http://pear.php.net/package/Console_Table/", + "keywords": [ + "console" + ], + "time": "2016-01-21 16:14:31" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.4" + }, + "platform-dev": [] +} diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..27b169a --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..1a28124 --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2016 Nils Adermann, Jordi Boggiano + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..147797c --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,10 @@ + $vendorDir . '/pear/console_table/Table.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ + $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + + $loader->register(true); + + return $loader; + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..f6fa437 --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,59 @@ +[ + { + "name": "pear/console_table", + "version": "v1.3.0", + "version_normalized": "1.3.0.0", + "source": { + "type": "git", + "url": "https://github.com/pear/Console_Table.git", + "reference": "64100b9ee81852f4fa17823e55d0b385a544f976" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pear/Console_Table/zipball/64100b9ee81852f4fa17823e55d0b385a544f976", + "reference": "64100b9ee81852f4fa17823e55d0b385a544f976", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "pear/Console_Color2": ">=0.1.2" + }, + "time": "2016-01-21 16:14:31", + "type": "library", + "installation-source": "dist", + "autoload": { + "classmap": [ + "Table.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Jan Schneider", + "homepage": "http://pear.php.net/user/yunosh" + }, + { + "name": "Tal Peer", + "homepage": "http://pear.php.net/user/tal" + }, + { + "name": "Xavier Noguer", + "homepage": "http://pear.php.net/user/xnoguer" + }, + { + "name": "Richard Heyes", + "homepage": "http://pear.php.net/user/richard" + } + ], + "description": "Library that makes it easy to build console style tables.", + "homepage": "http://pear.php.net/package/Console_Table/", + "keywords": [ + "console" + ] + } +] diff --git a/vendor/pear/console_table/.travis.yml b/vendor/pear/console_table/.travis.yml new file mode 100644 index 0000000..02de5fb --- /dev/null +++ b/vendor/pear/console_table/.travis.yml @@ -0,0 +1,9 @@ +language: php +install: + - pear install Console_Color2-alpha +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 +script: cd tests && pear run-tests . diff --git a/vendor/pear/console_table/Table.php b/vendor/pear/console_table/Table.php new file mode 100755 index 0000000..72d6bd8 --- /dev/null +++ b/vendor/pear/console_table/Table.php @@ -0,0 +1,974 @@ + + * @author Jan Schneider + * @copyright 2002-2005 Richard Heyes + * @copyright 2006-2008 Jan Schneider + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @version CVS: $Id$ + * @link http://pear.php.net/package/Console_Table + */ + +define('CONSOLE_TABLE_HORIZONTAL_RULE', 1); +define('CONSOLE_TABLE_ALIGN_LEFT', -1); +define('CONSOLE_TABLE_ALIGN_CENTER', 0); +define('CONSOLE_TABLE_ALIGN_RIGHT', 1); +define('CONSOLE_TABLE_BORDER_ASCII', -1); + +/** + * The main class. + * + * @category Console + * @package Console_Table + * @author Jan Schneider + * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) + * @link http://pear.php.net/package/Console_Table + */ +class Console_Table +{ + /** + * The table headers. + * + * @var array + */ + var $_headers = array(); + + /** + * The data of the table. + * + * @var array + */ + var $_data = array(); + + /** + * The maximum number of columns in a row. + * + * @var integer + */ + var $_max_cols = 0; + + /** + * The maximum number of rows in the table. + * + * @var integer + */ + var $_max_rows = 0; + + /** + * Lengths of the columns, calculated when rows are added to the table. + * + * @var array + */ + var $_cell_lengths = array(); + + /** + * Heights of the rows. + * + * @var array + */ + var $_row_heights = array(); + + /** + * How many spaces to use to pad the table. + * + * @var integer + */ + var $_padding = 1; + + /** + * Column filters. + * + * @var array + */ + var $_filters = array(); + + /** + * Columns to calculate totals for. + * + * @var array + */ + var $_calculateTotals; + + /** + * Alignment of the columns. + * + * @var array + */ + var $_col_align = array(); + + /** + * Default alignment of columns. + * + * @var integer + */ + var $_defaultAlign; + + /** + * Character set of the data. + * + * @var string + */ + var $_charset = 'utf-8'; + + /** + * Border characters. + * Allowed keys: + * - intersection - intersection ("+") + * - horizontal - horizontal rule character ("-") + * - vertical - vertical rule character ("|") + * + * @var array + */ + var $_border = array( + 'intersection' => '+', + 'horizontal' => '-', + 'vertical' => '|', + ); + + /** + * If borders are shown or not + * Allowed keys: top, right, bottom, left, inner: true and false + * + * @var array + */ + var $_borderVisibility = array( + 'top' => true, + 'right' => true, + 'bottom' => true, + 'left' => true, + 'inner' => true + ); + + /** + * Whether the data has ANSI colors. + * + * @var Console_Color2 + */ + var $_ansiColor = false; + + /** + * Constructor. + * + * @param integer $align Default alignment. One of + * CONSOLE_TABLE_ALIGN_LEFT, + * CONSOLE_TABLE_ALIGN_CENTER or + * CONSOLE_TABLE_ALIGN_RIGHT. + * @param string $border The character used for table borders or + * CONSOLE_TABLE_BORDER_ASCII. + * @param integer $padding How many spaces to use to pad the table. + * @param string $charset A charset supported by the mbstring PHP + * extension. + * @param boolean $color Whether the data contains ansi color codes. + */ + function __construct($align = CONSOLE_TABLE_ALIGN_LEFT, + $border = CONSOLE_TABLE_BORDER_ASCII, $padding = 1, + $charset = null, $color = false) + { + $this->_defaultAlign = $align; + $this->setBorder($border); + $this->_padding = $padding; + if ($color) { + if (!class_exists('Console_Color2')) { + include_once 'Console/Color2.php'; + } + $this->_ansiColor = new Console_Color2(); + } + if (!empty($charset)) { + $this->setCharset($charset); + } + } + + /** + * Converts an array to a table. + * + * @param array $headers Headers for the table. + * @param array $data A two dimensional array with the table + * data. + * @param boolean $returnObject Whether to return the Console_Table object + * instead of the rendered table. + * + * @static + * + * @return Console_Table|string A Console_Table object or the generated + * table. + */ + function fromArray($headers, $data, $returnObject = false) + { + if (!is_array($headers) || !is_array($data)) { + return false; + } + + $table = new Console_Table(); + $table->setHeaders($headers); + + foreach ($data as $row) { + $table->addRow($row); + } + + return $returnObject ? $table : $table->getTable(); + } + + /** + * Adds a filter to a column. + * + * Filters are standard PHP callbacks which are run on the data before + * table generation is performed. Filters are applied in the order they + * are added. The callback function must accept a single argument, which + * is a single table cell. + * + * @param integer $col Column to apply filter to. + * @param mixed &$callback PHP callback to apply. + * + * @return void + */ + function addFilter($col, &$callback) + { + $this->_filters[] = array($col, &$callback); + } + + /** + * Sets the charset of the provided table data. + * + * @param string $charset A charset supported by the mbstring PHP + * extension. + * + * @return void + */ + function setCharset($charset) + { + $locale = setlocale(LC_CTYPE, 0); + setlocale(LC_CTYPE, 'en_US'); + $this->_charset = strtolower($charset); + setlocale(LC_CTYPE, $locale); + } + + /** + * Set the table border settings + * + * Border definition modes: + * - CONSOLE_TABLE_BORDER_ASCII: Default border with +, - and | + * - array with keys "intersection", "horizontal" and "vertical" + * - single character string that sets all three of the array keys + * + * @param mixed $border Border definition + * + * @return void + * @see $_border + */ + function setBorder($border) + { + if ($border === CONSOLE_TABLE_BORDER_ASCII) { + $intersection = '+'; + $horizontal = '-'; + $vertical = '|'; + } else if (is_string($border)) { + $intersection = $horizontal = $vertical = $border; + } else if ($border == '') { + $intersection = $horizontal = $vertical = ''; + } else { + extract($border); + } + + $this->_border = array( + 'intersection' => $intersection, + 'horizontal' => $horizontal, + 'vertical' => $vertical, + ); + } + + /** + * Set which borders shall be shown. + * + * @param array $visibility Visibility settings. + * Allowed keys: left, right, top, bottom, inner + * + * @return void + * @see $_borderVisibility + */ + function setBorderVisibility($visibility) + { + $this->_borderVisibility = array_merge( + $this->_borderVisibility, + array_intersect_key( + $visibility, + $this->_borderVisibility + ) + ); + } + + /** + * Sets the alignment for the columns. + * + * @param integer $col_id The column number. + * @param integer $align Alignment to set for this column. One of + * CONSOLE_TABLE_ALIGN_LEFT + * CONSOLE_TABLE_ALIGN_CENTER + * CONSOLE_TABLE_ALIGN_RIGHT. + * + * @return void + */ + function setAlign($col_id, $align = CONSOLE_TABLE_ALIGN_LEFT) + { + switch ($align) { + case CONSOLE_TABLE_ALIGN_CENTER: + $pad = STR_PAD_BOTH; + break; + case CONSOLE_TABLE_ALIGN_RIGHT: + $pad = STR_PAD_LEFT; + break; + default: + $pad = STR_PAD_RIGHT; + break; + } + $this->_col_align[$col_id] = $pad; + } + + /** + * Specifies which columns are to have totals calculated for them and + * added as a new row at the bottom. + * + * @param array $cols Array of column numbers (starting with 0). + * + * @return void + */ + function calculateTotalsFor($cols) + { + $this->_calculateTotals = $cols; + } + + /** + * Sets the headers for the columns. + * + * @param array $headers The column headers. + * + * @return void + */ + function setHeaders($headers) + { + $this->_headers = array(array_values($headers)); + $this->_updateRowsCols($headers); + } + + /** + * Adds a row to the table. + * + * @param array $row The row data to add. + * @param boolean $append Whether to append or prepend the row. + * + * @return void + */ + function addRow($row, $append = true) + { + if ($append) { + $this->_data[] = array_values($row); + } else { + array_unshift($this->_data, array_values($row)); + } + + $this->_updateRowsCols($row); + } + + /** + * Inserts a row after a given row number in the table. + * + * If $row_id is not given it will prepend the row. + * + * @param array $row The data to insert. + * @param integer $row_id Row number to insert before. + * + * @return void + */ + function insertRow($row, $row_id = 0) + { + array_splice($this->_data, $row_id, 0, array($row)); + + $this->_updateRowsCols($row); + } + + /** + * Adds a column to the table. + * + * @param array $col_data The data of the column. + * @param integer $col_id The column index to populate. + * @param integer $row_id If starting row is not zero, specify it here. + * + * @return void + */ + function addCol($col_data, $col_id = 0, $row_id = 0) + { + foreach ($col_data as $col_cell) { + $this->_data[$row_id++][$col_id] = $col_cell; + } + + $this->_updateRowsCols(); + $this->_max_cols = max($this->_max_cols, $col_id + 1); + } + + /** + * Adds data to the table. + * + * @param array $data A two dimensional array with the table data. + * @param integer $col_id Starting column number. + * @param integer $row_id Starting row number. + * + * @return void + */ + function addData($data, $col_id = 0, $row_id = 0) + { + foreach ($data as $row) { + if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { + $this->_data[$row_id] = CONSOLE_TABLE_HORIZONTAL_RULE; + $row_id++; + continue; + } + $starting_col = $col_id; + foreach ($row as $cell) { + $this->_data[$row_id][$starting_col++] = $cell; + } + $this->_updateRowsCols(); + $this->_max_cols = max($this->_max_cols, $starting_col); + $row_id++; + } + } + + /** + * Adds a horizontal seperator to the table. + * + * @return void + */ + function addSeparator() + { + $this->_data[] = CONSOLE_TABLE_HORIZONTAL_RULE; + } + + /** + * Returns the generated table. + * + * @return string The generated table. + */ + function getTable() + { + $this->_applyFilters(); + $this->_calculateTotals(); + $this->_validateTable(); + + return $this->_buildTable(); + } + + /** + * Calculates totals for columns. + * + * @return void + */ + function _calculateTotals() + { + if (empty($this->_calculateTotals)) { + return; + } + + $this->addSeparator(); + + $totals = array(); + foreach ($this->_data as $row) { + if (is_array($row)) { + foreach ($this->_calculateTotals as $columnID) { + $totals[$columnID] += $row[$columnID]; + } + } + } + + $this->_data[] = $totals; + $this->_updateRowsCols(); + } + + /** + * Applies any column filters to the data. + * + * @return void + */ + function _applyFilters() + { + if (empty($this->_filters)) { + return; + } + + foreach ($this->_filters as $filter) { + $column = $filter[0]; + $callback = $filter[1]; + + foreach ($this->_data as $row_id => $row_data) { + if ($row_data !== CONSOLE_TABLE_HORIZONTAL_RULE) { + $this->_data[$row_id][$column] = + call_user_func($callback, $row_data[$column]); + } + } + } + } + + /** + * Ensures that column and row counts are correct. + * + * @return void + */ + function _validateTable() + { + if (!empty($this->_headers)) { + $this->_calculateRowHeight(-1, $this->_headers[0]); + } + + for ($i = 0; $i < $this->_max_rows; $i++) { + for ($j = 0; $j < $this->_max_cols; $j++) { + if (!isset($this->_data[$i][$j]) && + (!isset($this->_data[$i]) || + $this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE)) { + $this->_data[$i][$j] = ''; + } + + } + $this->_calculateRowHeight($i, $this->_data[$i]); + + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { + ksort($this->_data[$i]); + } + + } + + $this->_splitMultilineRows(); + + // Update cell lengths. + for ($i = 0; $i < count($this->_headers); $i++) { + $this->_calculateCellLengths($this->_headers[$i]); + } + for ($i = 0; $i < $this->_max_rows; $i++) { + $this->_calculateCellLengths($this->_data[$i]); + } + + ksort($this->_data); + } + + /** + * Splits multiline rows into many smaller one-line rows. + * + * @return void + */ + function _splitMultilineRows() + { + ksort($this->_data); + $sections = array(&$this->_headers, &$this->_data); + $max_rows = array(count($this->_headers), $this->_max_rows); + $row_height_offset = array(-1, 0); + + for ($s = 0; $s <= 1; $s++) { + $inserted = 0; + $new_data = $sections[$s]; + + for ($i = 0; $i < $max_rows[$s]; $i++) { + // Process only rows that have many lines. + $height = $this->_row_heights[$i + $row_height_offset[$s]]; + if ($height > 1) { + // Split column data into one-liners. + $split = array(); + for ($j = 0; $j < $this->_max_cols; $j++) { + $split[$j] = preg_split('/\r?\n|\r/', + $sections[$s][$i][$j]); + } + + $new_rows = array(); + // Construct new 'virtual' rows - insert empty strings for + // columns that have less lines that the highest one. + for ($i2 = 0; $i2 < $height; $i2++) { + for ($j = 0; $j < $this->_max_cols; $j++) { + $new_rows[$i2][$j] = !isset($split[$j][$i2]) + ? '' + : $split[$j][$i2]; + } + } + + // Replace current row with smaller rows. $inserted is + // used to take account of bigger array because of already + // inserted rows. + array_splice($new_data, $i + $inserted, 1, $new_rows); + $inserted += count($new_rows) - 1; + } + } + + // Has the data been modified? + if ($inserted > 0) { + $sections[$s] = $new_data; + $this->_updateRowsCols(); + } + } + } + + /** + * Builds the table. + * + * @return string The generated table string. + */ + function _buildTable() + { + if (!count($this->_data)) { + return ''; + } + + $vertical = $this->_border['vertical']; + $separator = $this->_getSeparator(); + + $return = array(); + for ($i = 0; $i < count($this->_data); $i++) { + for ($j = 0; $j < count($this->_data[$i]); $j++) { + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE && + $this->_strlen($this->_data[$i][$j]) < + $this->_cell_lengths[$j]) { + $this->_data[$i][$j] = $this->_strpad($this->_data[$i][$j], + $this->_cell_lengths[$j], + ' ', + $this->_col_align[$j]); + } + } + + if ($this->_data[$i] !== CONSOLE_TABLE_HORIZONTAL_RULE) { + $row_begin = $this->_borderVisibility['left'] + ? $vertical . str_repeat(' ', $this->_padding) + : ''; + $row_end = $this->_borderVisibility['right'] + ? str_repeat(' ', $this->_padding) . $vertical + : ''; + $implode_char = str_repeat(' ', $this->_padding) . $vertical + . str_repeat(' ', $this->_padding); + $return[] = $row_begin + . implode($implode_char, $this->_data[$i]) . $row_end; + } elseif (!empty($separator)) { + $return[] = $separator; + } + + } + + $return = implode(PHP_EOL, $return); + if (!empty($separator)) { + if ($this->_borderVisibility['inner']) { + $return = $separator . PHP_EOL . $return; + } + if ($this->_borderVisibility['bottom']) { + $return .= PHP_EOL . $separator; + } + } + $return .= PHP_EOL; + + if (!empty($this->_headers)) { + $return = $this->_getHeaderLine() . PHP_EOL . $return; + } + + return $return; + } + + /** + * Creates a horizontal separator for header separation and table + * start/end etc. + * + * @return string The horizontal separator. + */ + function _getSeparator() + { + if (!$this->_border) { + return; + } + + $horizontal = $this->_border['horizontal']; + $intersection = $this->_border['intersection']; + + $return = array(); + foreach ($this->_cell_lengths as $cl) { + $return[] = str_repeat($horizontal, $cl); + } + + $row_begin = $this->_borderVisibility['left'] + ? $intersection . str_repeat($horizontal, $this->_padding) + : ''; + $row_end = $this->_borderVisibility['right'] + ? str_repeat($horizontal, $this->_padding) . $intersection + : ''; + $implode_char = str_repeat($horizontal, $this->_padding) . $intersection + . str_repeat($horizontal, $this->_padding); + + return $row_begin . implode($implode_char, $return) . $row_end; + } + + /** + * Returns the header line for the table. + * + * @return string The header line of the table. + */ + function _getHeaderLine() + { + // Make sure column count is correct + for ($j = 0; $j < count($this->_headers); $j++) { + for ($i = 0; $i < $this->_max_cols; $i++) { + if (!isset($this->_headers[$j][$i])) { + $this->_headers[$j][$i] = ''; + } + } + } + + for ($j = 0; $j < count($this->_headers); $j++) { + for ($i = 0; $i < count($this->_headers[$j]); $i++) { + if ($this->_strlen($this->_headers[$j][$i]) < + $this->_cell_lengths[$i]) { + $this->_headers[$j][$i] = + $this->_strpad($this->_headers[$j][$i], + $this->_cell_lengths[$i], + ' ', + $this->_col_align[$i]); + } + } + } + + $vertical = $this->_border['vertical']; + $row_begin = $this->_borderVisibility['left'] + ? $vertical . str_repeat(' ', $this->_padding) + : ''; + $row_end = $this->_borderVisibility['right'] + ? str_repeat(' ', $this->_padding) . $vertical + : ''; + $implode_char = str_repeat(' ', $this->_padding) . $vertical + . str_repeat(' ', $this->_padding); + + $separator = $this->_getSeparator(); + if (!empty($separator) && $this->_borderVisibility['top']) { + $return[] = $separator; + } + for ($j = 0; $j < count($this->_headers); $j++) { + $return[] = $row_begin + . implode($implode_char, $this->_headers[$j]) . $row_end; + } + + return implode(PHP_EOL, $return); + } + + /** + * Updates values for maximum columns and rows. + * + * @param array $rowdata Data array of a single row. + * + * @return void + */ + function _updateRowsCols($rowdata = null) + { + // Update maximum columns. + $this->_max_cols = max($this->_max_cols, count($rowdata)); + + // Update maximum rows. + ksort($this->_data); + $keys = array_keys($this->_data); + $this->_max_rows = end($keys) + 1; + + switch ($this->_defaultAlign) { + case CONSOLE_TABLE_ALIGN_CENTER: + $pad = STR_PAD_BOTH; + break; + case CONSOLE_TABLE_ALIGN_RIGHT: + $pad = STR_PAD_LEFT; + break; + default: + $pad = STR_PAD_RIGHT; + break; + } + + // Set default column alignments + for ($i = 0; $i < $this->_max_cols; $i++) { + if (!isset($this->_col_align[$i])) { + $this->_col_align[$i] = $pad; + } + } + } + + /** + * Calculates the maximum length for each column of a row. + * + * @param array $row The row data. + * + * @return void + */ + function _calculateCellLengths($row) + { + for ($i = 0; $i < count($row); $i++) { + if (!isset($this->_cell_lengths[$i])) { + $this->_cell_lengths[$i] = 0; + } + $this->_cell_lengths[$i] = max($this->_cell_lengths[$i], + $this->_strlen($row[$i])); + } + } + + /** + * Calculates the maximum height for all columns of a row. + * + * @param integer $row_number The row number. + * @param array $row The row data. + * + * @return void + */ + function _calculateRowHeight($row_number, $row) + { + if (!isset($this->_row_heights[$row_number])) { + $this->_row_heights[$row_number] = 1; + } + + // Do not process horizontal rule rows. + if ($row === CONSOLE_TABLE_HORIZONTAL_RULE) { + return; + } + + for ($i = 0, $c = count($row); $i < $c; ++$i) { + $lines = preg_split('/\r?\n|\r/', $row[$i]); + $this->_row_heights[$row_number] = max($this->_row_heights[$row_number], + count($lines)); + } + } + + /** + * Returns the character length of a string. + * + * @param string $str A multibyte or singlebyte string. + * + * @return integer The string length. + */ + function _strlen($str) + { + static $mbstring; + + // Strip ANSI color codes if requested. + if ($this->_ansiColor) { + $str = $this->_ansiColor->strip($str); + } + + // Cache expensive function_exists() calls. + if (!isset($mbstring)) { + $mbstring = function_exists('mb_strwidth'); + } + + if ($mbstring) { + return mb_strwidth($str, $this->_charset); + } + + return strlen($str); + } + + /** + * Returns part of a string. + * + * @param string $string The string to be converted. + * @param integer $start The part's start position, zero based. + * @param integer $length The part's length. + * + * @return string The string's part. + */ + function _substr($string, $start, $length = null) + { + static $mbstring; + + // Cache expensive function_exists() calls. + if (!isset($mbstring)) { + $mbstring = function_exists('mb_substr'); + } + + if (is_null($length)) { + $length = $this->_strlen($string); + } + if ($mbstring) { + $ret = @mb_substr($string, $start, $length, $this->_charset); + if (!empty($ret)) { + return $ret; + } + } + return substr($string, $start, $length); + } + + /** + * Returns a string padded to a certain length with another string. + * + * This method behaves exactly like str_pad but is multibyte safe. + * + * @param string $input The string to be padded. + * @param integer $length The length of the resulting string. + * @param string $pad The string to pad the input string with. Must + * be in the same charset like the input string. + * @param const $type The padding type. One of STR_PAD_LEFT, + * STR_PAD_RIGHT, or STR_PAD_BOTH. + * + * @return string The padded string. + */ + function _strpad($input, $length, $pad = ' ', $type = STR_PAD_RIGHT) + { + $mb_length = $this->_strlen($input); + $sb_length = strlen($input); + $pad_length = $this->_strlen($pad); + + /* Return if we already have the length. */ + if ($mb_length >= $length) { + return $input; + } + + /* Shortcut for single byte strings. */ + if ($mb_length == $sb_length && $pad_length == strlen($pad)) { + return str_pad($input, $length, $pad, $type); + } + + switch ($type) { + case STR_PAD_LEFT: + $left = $length - $mb_length; + $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), + 0, $left, $this->_charset) . $input; + break; + case STR_PAD_BOTH: + $left = floor(($length - $mb_length) / 2); + $right = ceil(($length - $mb_length) / 2); + $output = $this->_substr(str_repeat($pad, ceil($left / $pad_length)), + 0, $left, $this->_charset) . + $input . + $this->_substr(str_repeat($pad, ceil($right / $pad_length)), + 0, $right, $this->_charset); + break; + case STR_PAD_RIGHT: + $right = $length - $mb_length; + $output = $input . + $this->_substr(str_repeat($pad, ceil($right / $pad_length)), + 0, $right, $this->_charset); + break; + } + + return $output; + } + +} diff --git a/vendor/pear/console_table/composer.json b/vendor/pear/console_table/composer.json new file mode 100644 index 0000000..cfc37a3 --- /dev/null +++ b/vendor/pear/console_table/composer.json @@ -0,0 +1,43 @@ +{ + "name": "pear/console_table", + "type": "library", + "description": "Library that makes it easy to build console style tables.", + "keywords": [ + "console" + ], + "homepage": "http://pear.php.net/package/Console_Table/", + "license": "BSD-2-Clause", + "authors": [ + { + "name": "Jan Schneider", + "homepage": "http://pear.php.net/user/yunosh" + }, + { + "name": "Tal Peer", + "homepage": "http://pear.php.net/user/tal" + }, + { + "name": "Xavier Noguer", + "homepage": "http://pear.php.net/user/xnoguer" + }, + { + "name": "Richard Heyes", + "homepage": "http://pear.php.net/user/richard" + } + ], + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "pear/Console_Color2": ">=0.1.2" + }, + "autoload": { + "classmap": [ + "Table.php" + ] + }, + "support": { + "issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_Table", + "source": "https://github.com/pear/Console_Table" + } +} diff --git a/vendor/pear/console_table/package.xml b/vendor/pear/console_table/package.xml new file mode 100644 index 0000000..ac8ee5f --- /dev/null +++ b/vendor/pear/console_table/package.xml @@ -0,0 +1,401 @@ + + + Console_Table + pear.php.net + Library that makes it easy to build console style tables + Provides a Console_Table class with methods such as addRow(), insertRow(), addCol() etc. to build console tables with or without headers and with user defined table rules, padding, and alignment. + + Jan Schneider + yunosh + jan@horde.org + yes + + + Richard Heyes + richard + richard@phpguru.org + no + + + Tal Peer + tal + tal@php.net + no + + + Xavier Noguer + xnoguer + xnoguer@php.net + no + + 2016-01-21 + + 1.3.0 + 1.3.0 + + + stable + stable + + BSD + +* Fix warning with PHP 7 and bump required PHP version to 5.2.0 (Pieter Frenssen PR #13). + + + + + + + + + + + + + + + + + + + + + + + + + + + 5.2.0 + + + 1.4.0b1 + + + + + Console_Color2 + pear.php.net + 0.1.2 + + + + + + + + 0.8 + 0.8 + + + beta + beta + + 2002-09-02 + BSD + +* Initial release. + + + + + 1.0 + 1.0.0 + + + stable + stable + + 2003-01-24 + BSD + +* Removed a few options and added addData() method. + + + + + 1.0.1 + 1.0.0 + + + stable + stable + + 2003-03-03 + BSD + +* Fixed a caching bug. + + + + + 1.0.2 + 1.0.0 + + + stable + stable + + 2005-07-16 + BSD + +* Added support for column alignment (Michael Richter). + + + + + 1.0.3 + 1.0.0 + + + stable + stable + + 2006-03-13 + BSD + +* Fix cell width calculation if setting header with associative array (Bug #4299). +* Fix fatal reference error with some PHP versions (Bug #5309). +* Fix notice if no data has been provided (Bug #5851). +* Added multibyte support (Requests #2934, Request #7014). + + + + + 1.0.4 + 1.0.0 + + + stable + stable + + 2006-04-08 + BSD + +* Add support for multi-line cells (koto at webworkers dot pl, Request #7017). + + + + + 1.0.5 + 1.0.0 + + + stable + stable + + 2006-08-28 + BSD + +* Allow to specify separator rules in addData(). +* Fix warnings when combining separator rules and callback filters (Bug #8566). + + + + + 1.0.6 + 1.0.0 + + + stable + stable + + 2007-01-19 + BSD + +* Add support for multi-line headers (Request #8615). + + + + 2007-05-17 + + 1.0.7 + 1.0.0 + + + stable + stable + + BSD + +* Fix header height if first data row has more than one line (Bug #11064). +* Fix notice if header is not set. + + + + 2008-01-09 + + 1.0.8 + 1.0.0 + + + stable + stable + + BSD + +* Fix cell padding with multibyte strings under certain circumstances (Bug #12853). + + + + 2008-03-28 + + 1.1.0 + 1.1.0 + + + stable + stable + + BSD + +* Add option to set table border character. +* Extend constructor to set table borders, padding, and charset on instantiation. + + + + 2008-04-09 + + 1.1.1 + 1.1.0 + + + stable + stable + + BSD + +* Fix rendering of multiline rows with cells that contain zeros (Bug #13629). + + + + 2008-07-27 + + 1.1.2 + 1.1.0 + + + stable + stable + + BSD + +* Don't render anything if no data has been provided (Bug #14405). + + + + 2008-10-20 + + 1.1.3 + 1.1.1 + + + stable + stable + + BSD + +* Add option to render data with ANSI color codes (Igor Feghali, Request #14835). + + + + + 1.1.4 + 1.1.1 + + + stable + stable + + 2010-10-25 + BSD + +* Automatically built QA release. +* Add Console_Color support (Request #14835). + +* Improve documentation (Christian Weiske, Bug #15006). + + + + 2012-12-07 + + + 1.1.5 + 1.1.1 + + + stable + stable + + BSD + +* Use mb_strwidth() instead of mb_strlen() to determine lengths of multi-byte strings (Bug #19423). + + + + 2013-10-12 + + 1.1.6 + 1.1.1 + + + stable + stable + + BSD + +* Use line breaks dependent on the current operating system (Bug #20092). + + + + 2014-02-17 + + 1.2.0 + 1.2.0 + + + stable + stable + + BSD + +* Make border visibility configurable (Christian Weiske, Request #20186). +* Allow to customize all border characters (Christian Weiske, Request #20182). +* Fix notice when using setAlign() on other than first column (Christian Weiske, Bug #20181). +* Use Console_Color2 to avoid notices from PHP 4 code (Christian Weiske, Bug #20188) + + + + 2014-10-27 + + 1.2.1 + 1.2.0 + + + stable + stable + + BSD + +* Add travis configuration (Christian Weiske). +* Try to autoload Console_Color2 first (Jurgen Rutten, PR #11). +* Fix Composer definition syntax (Rob Loach, PR #9). + + + + 2016-01-21 + + 1.3.0 + 1.3.0 + + + stable + stable + + BSD + +* Fix warning with PHP 7 and bump required PHP version to 5.2.0 (Pieter Frenssen PR #13). + + + + diff --git a/vendor/pear/console_table/tests/assoziative_arrays.phpt b/vendor/pear/console_table/tests/assoziative_arrays.phpt new file mode 100644 index 0000000..91bc49b --- /dev/null +++ b/vendor/pear/console_table/tests/assoziative_arrays.phpt @@ -0,0 +1,35 @@ +--TEST-- +Header and data as associative arrays. +--FILE-- + 'foo', + 'two' => 'bar' +); + +$data = array( + array( + 'x' => 'baz', + ) +); + +$table = new Console_Table(); +$table->setHeaders($headers); +$table->addData($data); + +echo $table->getTable(); + +?> +--EXPECT-- ++-----+-----+ +| foo | bar | ++-----+-----+ +| baz | | ++-----+-----+ diff --git a/vendor/pear/console_table/tests/border-ascii.phpt b/vendor/pear/console_table/tests/border-ascii.phpt new file mode 100644 index 0000000..e8ca631 --- /dev/null +++ b/vendor/pear/console_table/tests/border-ascii.phpt @@ -0,0 +1,24 @@ +--TEST-- +Border: default ASCII mode +--FILE-- +setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +echo $table->getTable(); +?> +--EXPECT-- ++----------+------------+ +| City | Mayor | ++----------+------------+ +| Leipzig | Major Tom | +| New York | Towerhouse | ++----------+------------+ diff --git a/vendor/pear/console_table/tests/border-custom.phpt b/vendor/pear/console_table/tests/border-custom.phpt new file mode 100644 index 0000000..62be737 --- /dev/null +++ b/vendor/pear/console_table/tests/border-custom.phpt @@ -0,0 +1,27 @@ +--TEST-- +Border: new custom mode +--FILE-- + '=', 'vertical' => ':', 'intersection' => '*') +); +$table->setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +echo $table->getTable(); +?> +--EXPECT-- +*==========*============* +: City : Mayor : +*==========*============* +: Leipzig : Major Tom : +: New York : Towerhouse : +*==========*============* diff --git a/vendor/pear/console_table/tests/border-custom2.phpt b/vendor/pear/console_table/tests/border-custom2.phpt new file mode 100644 index 0000000..c129c8d --- /dev/null +++ b/vendor/pear/console_table/tests/border-custom2.phpt @@ -0,0 +1,27 @@ +--TEST-- +Border: new custom mode, alternative style +--FILE-- + '=', 'vertical' => '', 'intersection' => '') +); +$table->setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +echo $table->getTable(); +?> +--EXPECT-- +====================== + City Mayor +====================== + Leipzig Major Tom + New York Towerhouse +====================== diff --git a/vendor/pear/console_table/tests/border-disable.phpt b/vendor/pear/console_table/tests/border-disable.phpt new file mode 100644 index 0000000..c753e98 --- /dev/null +++ b/vendor/pear/console_table/tests/border-disable.phpt @@ -0,0 +1,68 @@ +--TEST-- +Border: disable it +--FILE-- +setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +$table->setBorderVisibility( + array( + 'left' => false, + 'right' => false, + ) +); +echo "Horizontal borders only:\n"; +echo $table->getTable() . "\n"; + +$table->setBorderVisibility( + array( + 'top' => false, + 'right' => false, + 'bottom' => false, + 'left' => false, + 'inner' => false, + ) +); +echo "No borders:\n"; +echo $table->getTable() . "\n"; + +$table->setBorderVisibility( + array( + 'top' => false, + 'right' => true, + 'bottom' => false, + 'left' => true, + 'inner' => true, + ) +); +echo "Vertical and inner only:\n"; +echo $table->getTable() . "\n"; +?> +--EXPECT-- +Horizontal borders only: +---------+----------- +City | Mayor +---------+----------- +Leipzig | Major Tom +New York | Towerhouse +---------+----------- + +No borders: +City | Mayor +Leipzig | Major Tom +New York | Towerhouse + +Vertical and inner only: +| City | Mayor | ++----------+------------+ +| Leipzig | Major Tom | +| New York | Towerhouse | + diff --git a/vendor/pear/console_table/tests/border-dot.phpt b/vendor/pear/console_table/tests/border-dot.phpt new file mode 100644 index 0000000..8d6f103 --- /dev/null +++ b/vendor/pear/console_table/tests/border-dot.phpt @@ -0,0 +1,24 @@ +--TEST-- +Border: custom border character +--FILE-- +setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +echo $table->getTable(); +?> +--EXPECT-- +......................... +. City . Mayor . +......................... +. Leipzig . Major Tom . +. New York . Towerhouse . +......................... diff --git a/vendor/pear/console_table/tests/border-empty.phpt b/vendor/pear/console_table/tests/border-empty.phpt new file mode 100644 index 0000000..a9c635b --- /dev/null +++ b/vendor/pear/console_table/tests/border-empty.phpt @@ -0,0 +1,21 @@ +--TEST-- +Border: empty character +--FILE-- +setHeaders(array('City', 'Mayor')); +$table->addRow(array('Leipzig', 'Major Tom')); +$table->addRow(array('New York', 'Towerhouse')); + +echo $table->getTable() . "\n"; +?> +--EXPECT-- + City Mayor + Leipzig Major Tom + New York Towerhouse diff --git a/vendor/pear/console_table/tests/bug20181.phpt b/vendor/pear/console_table/tests/bug20181.phpt new file mode 100644 index 0000000..2a604b3 --- /dev/null +++ b/vendor/pear/console_table/tests/bug20181.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #20181: setAlign() on non-zero column +--FILE-- +setAlign(1, CONSOLE_TABLE_ALIGN_RIGHT); +$table->setHeaders(array('f', 'bar')); +$table->addRow(array('baz', 'b')); + +echo $table->getTable(); +?> +--EXPECT-- ++-----+-----+ +| f | bar | ++-----+-----+ +| baz | b | ++-----+-----+ diff --git a/vendor/pear/console_table/tests/colors.phpt b/vendor/pear/console_table/tests/colors.phpt new file mode 100644 index 0000000..ac7f923 --- /dev/null +++ b/vendor/pear/console_table/tests/colors.phpt @@ -0,0 +1,28 @@ +--TEST-- +Data with ANSI color codes +--SKIPIF-- + +--FILE-- +setHeaders(array('foo', 'bar')); +$table->addRow(array('baz', $cc->convert("%bblue%n"))); + +echo $table->getTable(); + +?> +--EXPECT-- ++-----+------+ +| foo | bar | ++-----+------+ +| baz | blue | ++-----+------+ diff --git a/vendor/pear/console_table/tests/filters.phpt b/vendor/pear/console_table/tests/filters.phpt new file mode 100644 index 0000000..f96e78a --- /dev/null +++ b/vendor/pear/console_table/tests/filters.phpt @@ -0,0 +1,38 @@ +--TEST-- +Callback filters +--FILE-- +setHeaders(array('foo', 'bar')); +$table->addData($data); +$table->addFilter(0, $filter); + +echo $table->getTable(); + +?> +--EXPECT-- ++-------+-------+ +| foo | bar | ++-------+-------+ +| ONE | two | +| THREE | four | ++-------+-------+ +| FIVE | six | +| SEVEN | eight | ++-------+-------+ diff --git a/vendor/pear/console_table/tests/multibyte.phpt b/vendor/pear/console_table/tests/multibyte.phpt new file mode 100644 index 0000000..0ac7723 --- /dev/null +++ b/vendor/pear/console_table/tests/multibyte.phpt @@ -0,0 +1,35 @@ +--TEST-- +Multibyte strings +--FILE-- +setHeaders(array('Schön', 'Häßlich')); +$table->addData(array(array('Ich', 'Du'), array('Ä', 'Ü'))); +echo $table->getTable(); + +$table = new Console_Table(); +$table->addRow(array("I'm from 中国")); +$table->addRow(array("我是中国人")); +$table->addRow(array("I'm from China")); +echo $table->getTable(); + +?> +--EXPECT-- ++-------+---------+ +| Schön | Häßlich | ++-------+---------+ +| Ich | Du | +| Ä | Ü | ++-------+---------+ ++----------------+ +| I'm from 中国 | +| 我是中国人 | +| I'm from China | ++----------------+ diff --git a/vendor/pear/console_table/tests/multiline.phpt b/vendor/pear/console_table/tests/multiline.phpt new file mode 100644 index 0000000..1e72e58 --- /dev/null +++ b/vendor/pear/console_table/tests/multiline.phpt @@ -0,0 +1,51 @@ +--TEST-- +Multiline table cells +--FILE-- +setHeaders(array("h1\nmultiline", 'h2', "h3", 'h4')); +$table->addData($data); +echo $table->getTable(); + +echo Console_Table::fromArray(array('one line header'), + array(array("multiple\nlines"), + array('one line'))); + +?> +--EXPECT-- ++-----------+--------+-----------+--------+ +| h1 | h2 | h3 | h4 | +| multiline | | | | ++-----------+--------+-----------+--------+ +| col1 | 0 | col3 | col4 | +| | | multiline | | +| r2col1 | r2col2 | r2col3 | r2col4 | +| | | multiline | | +| r3col1 | r3col2 | r3col3 | r3col4 | +| | | multiline | | +| | | verymuch | | +| r4col1 | r4col2 | r4col3 | r4col4 | +| r5col1 | r5col2 | r5col3 | r5col4 | ++-----------+--------+-----------+--------+ ++-----------------+ +| one line header | ++-----------------+ +| multiple | +| lines | +| one line | ++-----------------+ diff --git a/vendor/pear/console_table/tests/no_header.phpt b/vendor/pear/console_table/tests/no_header.phpt new file mode 100644 index 0000000..8d4b61b --- /dev/null +++ b/vendor/pear/console_table/tests/no_header.phpt @@ -0,0 +1,21 @@ +--TEST-- +Table without header +--FILE-- +addData(array(array('foo', 'bar'))); + +echo $table->getTable(); + +?> +--EXPECT-- ++-----+-----+ +| foo | bar | ++-----+-----+ diff --git a/vendor/pear/console_table/tests/no_rows.phpt b/vendor/pear/console_table/tests/no_rows.phpt new file mode 100644 index 0000000..386da34 --- /dev/null +++ b/vendor/pear/console_table/tests/no_rows.phpt @@ -0,0 +1,25 @@ +--TEST-- +Table without data +--FILE-- +setHeaders(array('foo', 'bar')); +echo $table->getTable(); + +$table = new Console_Table(); +echo $table->getTable(); + +?> +--EXPECT-- ++-----+-----+ +| foo | bar | ++-----+-----+ +| | | ++-----+-----+ diff --git a/vendor/pear/console_table/tests/rules.phpt b/vendor/pear/console_table/tests/rules.phpt new file mode 100644 index 0000000..ddbbc3f --- /dev/null +++ b/vendor/pear/console_table/tests/rules.phpt @@ -0,0 +1,74 @@ +--TEST-- +Horizontal rules +--FILE-- +setHeaders(array('foo', 'bar')); +$table->addData($data); +$table->addSeparator(); +echo $table->getTable(); +echo "=========================\n"; + +$table = new Console_Table(CONSOLE_TABLE_ALIGN_LEFT, ''); +$table->setHeaders(array('foo', 'bar')); +$table->addData($data); +$table->addSeparator(); +echo $table->getTable(); +echo "=========================\n"; + +$table = new Console_Table(CONSOLE_TABLE_ALIGN_LEFT, '#', 0); +$table->setHeaders(array('foo', 'bar')); +$table->addData($data); +$table->addSeparator(); +echo $table->getTable(); + +?> +--EXPECT-- ++-------+-------+ +| foo | bar | ++-------+-------+ +| one | two | ++-------+-------+ +| three | four | ++-------+-------+ ++-------+-------+ +| five | six | +| seven | eight | ++-------+-------+ ++-------+-------+ +========================= + foo bar + one two + three four + five six + seven eight +========================= +############# +#foo #bar # +############# +#one #two # +############# +#three#four # +############# +############# +#five #six # +#seven#eight# +############# +#############