<?php

namespace BootPress\SQLite;

use BootPress\Database\Component as Database;

class Component extends Database
{
    /** @var object A BootPress\SQLite\Fts instance. */
    public $fts;

    /** @var bool Whether or not this is a new database. */
    public $created = false;

    /** @var array The database's settings. */
    private $info = array();

    /**
     * Connects to an SQLite database **$file**, and creates one if it doesn't already exist.
     *
     * @param string $file The SQLite database file location, or just leave it ``null`` to create an SQLite database in *':memory:'*.
     */
    public function __construct($file = null)
    {
        if (is_null($file)) {
            $file = ':memory:';
            $this->created = true;
        } else {
            if (!is_file($file)) {
                if (!is_dir(dirname($file))) {
                    mkdir(dirname($file), 0755, true);
                }
                $this->created = true;
            }
            if (class_exists('BootPress\Page\Component') && class_exists('Symfony\Component\Yaml\Yaml')) {
                $page = \BootPress\Page\Component::html();
                $databases = $page->file('databases.yml');
                $yaml = (is_file($databases)) ? \Symfony\Component\Yaml\Yaml::parse(file_get_contents($databases)) : array();
                if (!isset($yaml['sqlite'])) {
                    $yaml['sqlite'] = array();
                }
                if (!in_array($file, $yaml['sqlite'])) {
                    $yaml['sqlite'][] = $file;
                    ksort($yaml);
                    sort($yaml['sqlite']);
                    $yaml = \Symfony\Component\Yaml\Yaml::dump($yaml, 3);
                    file_put_contents($databases, $yaml);
                }
            }
        }
        $this->driver($file);
        $this->connection = new \SQLite3($file);
        $this->connection->exec('PRAGMA foreign_keys = ON');
        $this->fts = new Fts($this);
    }

    /**
     * Either create an SQLite **$table** if it has not already been created, or verify that it matches the sqlite_master table index. If something has changed, then the **$table** will be altered accordingly.
     *
     * @param string $table   The database table name.
     * @param array  $fields  An ``array($name => $type, ...)`` of fields that define this **$table**.
     * @param mixed  $index   A string of comma-separated '**field, name, ...**'s to index. If you are creating multiple indexes, then make this an ``array('field', 'name', ... )`` of all the indexes you would like to create. If it is a unique index, then make it an ``array('unique' => 'field, name, ...')``.
     * @param array  $changes When changing field names, make an ``array($old => $new, ...)`` to map the old field name with the new field name, so that all of the data is updated accordingly. You can change the **$fields** order and type no problem, but if you change field names and don't map them, we'll send the old (missing) field name to the scrapheap, and every new field name will receive it's default value.
     *
     * @return bool Either ``false`` if nothing has changed and the **$table** is exactly as you would like it, or ``true`` if the **$table** has been newly created or updated in any way.
     *
     * @example
     *
     * ```php
     * if ($db->created) {
     *
     *     $db->create('employees', array(
     *         'id' => 'INTEGER PRIMARY KEY',
     *         'name' => 'TEXT COLLATE NOCASE',
     *         'position' => 'TEXT NOT NULL DEFAULT ""',
     *     ), array('unique'=>'position'));
     *
     *     // Wait, I just changed my mind
     *     $db->create('employees', array(
     *         'id' => 'INTEGER PRIMARY KEY',
     *         'name' => 'TEXT UNIQUE COLLATE NOCASE',
     *         'title' => 'TEXT DEFAULT ""',
     *     ), 'title', array(
     *         'position' => 'title',
     *     ));
     *
     * }
     * ```
     */
    public function create($table, array $fields, $index = array(), array $changes = array())
    {
        $columns = array();
        foreach ($fields as $name => $type) {
            $columns[] = (is_int($name)) ? $type : $name.' '.$type;
        }
        $columns = implode(", \n\t", $columns);
        $query = 'CREATE TABLE '.$table.' ('.$columns.')';
        $executed = $this->info('tables', $table);
        // See http://www.sqlite.org/fileformat2.html - 2.5 Storage Of The SQL Database Schema
        if (preg_replace('/(\'|")/', '', $query) == preg_replace('/(\'|")/', '', $executed)) {
            $this->index($table, $index); // make sure they are all correct also
            return false; // the table has already been created in it's requested state
        }
        $this->info('tables', $table, $query); // to either add or update
        if ($executed) { // then this table is being altered in some way
            $this->index($table, '');
            $this->alter($table, $fields, $changes, $columns);
        } else {
            $this->exec($query); // We should only get here once
        }
        $this->index($table, $index);

        return true; // the table has been created (or altered)
    }

    /**
     * Create and retrieve database settings.
     *
     * @param string $name  What you want to either set or return.
     * @param mixed  $value The setting's value. If you want to remove the setting, then set this explicitly to ``null``.
     *
     * @return mixed An array of all the settings (if no parameters are given), or the setting's value (if no value is given).
     *
     * @example
     *
     * ```php
     * $db->settings('version', '1.2');
     *
     * echo $db->settings('version'); // 1.2
     * ```
     */
    public function settings($name = null, $value = null)
    {
        switch (func_num_args()) {
            case 0: // they want it all
                return $this->info('settings');
                break;
            case 1: // they want to retrieve a specific setting
                return $this->info('settings', func_get_arg(0));
                break;
            case 2: // they want to establish a setting
                $update = false;
                list($name, $value) = func_get_args();
                $current = $this->info('settings', $name);
                if (is_null($value)) {
                    // then we don't want this in the database as "null" is the default value
                    if (!is_null($current)) {
                        unset($this->info['settings'][$name]);
                        $update = true;
                    }
                } elseif ($current !== $value) {
                    $this->info['settings'][$name] = $value;
                    $update = true;
                }
                if ($update) {
                    $this->exec('UPDATE config SET settings = ?', serialize($this->info['settings']));
                }
                break;
        }
    }

    /**
     * Returns the ``$field . 'IN(' . implode(',', $ids) . ')'``, in the same order given.  This method is patterned after using MySQL's [FIELD()](http://dba.stackexchange.com/questions/109120/how-does-order-by-field-in-mysql-work-internally) function, which unfortunately is unavailable in SQLite.
     *
     * @param string $field Database column.
     * @param array  $ids   Those passed to the IN() clause.
     *
     * @return string An SQL string to put at the end of your query.
     *
     * @example
     *
     * ```php
     * if ($ids = $db->ids('SELECT id FROM employees ORDER BY name ASC')) {
     *     foreach ($db->all(array(
     *         'SELECT name, title FROM employees',
     *         'WHERE '.$db->inOrder('id', $ids),
     *     )) as $row) {
     *         list($name, $title) = $row;
     *     }
     * }
     * ```
     */
    public function inOrder($field, array $ids)
    {
        $sql = $field.' IN('.implode(',', $ids).') ORDER BY CASE '.$field;
        foreach (array_values($ids) as $num => $id) {
            $sql .= ' WHEN '.$id.' THEN '.$num;
        }
        $sql .= ' ELSE NULL END ASC';

        return $sql;
    }

    /**
     * When you overwhelm an SQLite database with overlapping inserts and updates, there's a chance it may become corrupted.  If it does, I've been able to recreate it using this method.
     *
     * @param string $file The **NEW** SQLite database file location.  The one you want to create.
     */
    public function recreate($file)
    {
        if (is_file($file)) {
            return;
        }
        $virtual = $tables = $indexes = array();
        if ($result = $this->query('SELECT type, name, sql FROM sqlite_master')) {
            while (list($type, $name, $sql) = $this->fetch($result)) {
                if (!empty($sql)) {
                    switch ($type) {
                        case 'table':
                            $tables[$name] = $sql;
                            break;
                        case 'index':
                            $indexes[] = $sql;
                            break;
                    }
                }
            }
            $this->close($result);
        }
        foreach ($tables as $name => $sql) {
            if (strpos($sql, 'VIRTUAL TABLE')) {
                $virtual[] = $name;
            }
        }
        foreach ($virtual as $table) {
            foreach ($tables as $name => $sql) {
                if (strpos($name, "{$table}_") === 0) {
                    unset($tables[$name]);
                }
            }
        }
        $db = new self($file);
        $this->exec('ATTACH DATABASE '.$this->dbEscape($file).' AS recreate');
        foreach ($tables as $table => $sql) {
            $db->connection()->exec($sql);
            if ($fields = $this->row('SELECT * FROM '.$table.' LIMIT 1', '', 'assoc')) {
                $fields = implode(', ', array_keys($fields));
                $this->exec("INSERT INTO recreate.{$table} ({$fields}) SELECT * FROM {$table}");
            }
        }
        foreach ($indexes as $sql) {
            $db->connection()->exec($sql);
        }
        $db->connection()->close();
    }

    private function alter($table, array $fields, array $changes, $columns)
    {
        $map = array();
        if ($compare = $this->row('SELECT * FROM '.$table.' LIMIT 1', array(), 'assoc')) {
            foreach ($changes as $old => $new) {
                if (isset($fields[$new]) && isset($compare[$old])) {
                    $map[$old] = $new; // legitimate changes
                }
            }
            foreach (array_keys($compare) as $field) {
                if (isset($fields[$field]) && !isset($map[$field])) {
                    $map[$field] = $field; // old fields that match the new
                }
            }
        }
        $this->connection->exec('PRAGMA foreign_keys = OFF');
        $this->connection->exec('BEGIN IMMEDIATE');
        $result = true;
        if ($result !== false) {
            $result = $this->exec("CREATE TABLE {$table}_copy ({$columns})");
        }
        if (!empty($map)) {
            $new = implode(', ', array_values($map));
            $old = implode(', ', array_keys($map));
            if ($result !== false) {
                $result = $this->exec("INSERT INTO {$table}_copy ({$new}) SELECT {$old} FROM {$table}");
            }
        }
        if ($result !== false) {
            $result = $this->exec("DROP TABLE {$table}");
        }
        if ($result !== false) {
            $result = $this->exec("ALTER TABLE {$table}_copy RENAME TO {$table}");
        }
        $this->connection->exec($result !== false ? 'COMMIT' : 'ROLLBACK');
        $this->connection->exec('PRAGMA foreign_keys = ON');
    }

    private function index($table, $columns)
    {
        $queries = array();
        $outdated = $this->info('indexes', $table);
        if (empty($outdated)) {
            $outdated = array();
        }
        if (!empty($columns)) {
            foreach ((array) $columns as $key => $indexes) {
                $unique = (!is_int($key) && strtolower($key) == 'unique') ? ' UNIQUE ' : ' ';
                $indexes = array_map('trim', explode(',', $indexes));
                $name = $table.'_'.implode('_', $indexes);
                $sql = "CREATE{$unique}INDEX {$name} ON {$table} (".implode(', ', $indexes).')';
                $queries[$name] = $sql;
                if (!isset($outdated[$name]) || $outdated[$name] != $sql) {
                    if (isset($outdated[$name])) {
                        $this->exec('DROP INDEX '.$name);
                    }
                    $this->exec($sql);
                }
            }
            foreach ($outdated as $name => $sql) {
                if (!isset($queries[$name])) {
                    $this->exec('DROP INDEX '.$name);
                }
            }
            $this->info('indexes', $table, $queries);
        }
    }

    /**
     * Only made public so that ``$this->fts`` can call it, and it's not documented to discourage it's use.
     */
    public function info($master) // only made public so that $this->fts can call it
    {
        if ($master == 'settings') {
            if (!isset($this->info['settings'])) {
                if ($this->create('config', array('settings' => 'TEXT NOT NULL DEFAULT ""'))) {
                    $this->exec('INSERT INTO config (settings) VALUES (?)', serialize(array()));
                }
                $this->info['settings'] = array();
                if ($settings = $this->value('SELECT settings FROM config')) {
                    $this->info['settings'] = unserialize($settings);
                }
            }
        } elseif (!isset($this->info[$master])) { // 'tables' or 'indexes'
            if ($result = $this->query('SELECT type, name, tbl_name, sql FROM sqlite_master')) {
                while (list($type, $name, $table, $sql) = $this->fetch($result)) {
                    switch ($type) {
                        case 'table':
                            $this->info['tables'][$table] = $sql;
                            break;
                        case 'index':
                            if (!empty($sql)) {
                                $this->info['indexes'][$table][$name] = $sql;
                            }
                            break;
                    }
                }
                $this->close($result);
            }
        }
        switch (func_num_args()) {
            case 3:
                list($master, $name, $add) = func_get_args();
                $this->info[$master][$name] = $add;
                break;
            case 2:
                list($master, $name) = func_get_args();

                return (isset($this->info[$master][$name])) ? $this->info[$master][$name] : null;
                break;
            case 1:
                list($master) = func_get_args();

                return (isset($this->info[$master])) ? $this->info[$master] : null;
                break;
        }
    }

    protected function dbPrepare($query)
    {
        try {
            return $this->connection->prepare($query); // returns (mixed) $stmt object or false
        } catch (\Exception $e) {
            return false;
        }
    }

    protected function dbPrepareError()
    {
        return ($msg = $this->connection->lastErrorMsg()) ? 'Code: '.$this->connection->lastErrorCode()." Error: {$msg}" : false; // returns (string) error or false
    }

    protected function dbExecute($stmt, array $values, $reference)
    {
        if (isset($this->prepared[$reference]['result'])) {
            $this->prepared[$reference]['result']->finalize();
            unset($this->prepared[$reference]['result']);
            $stmt->reset();
        }
        foreach (array_values($values) as $key => $value) {
            switch (gettype($value)) {
                case 'boolean':
                case 'integer':
                    $type = SQLITE3_INTEGER;
                    break;
                case 'double':
                    $type = SQLITE3_FLOAT;
                    break;
                case 'NULL':
                    $type = SQLITE3_NULL;
                    break;
                default:
                    $type = SQLITE3_TEXT;
                    break;
            }
            $stmt->bindValue($key + 1, $value, $type);
        }
        // Throws an ErrorException when a constraint fails eg. a (datatype mismatch)[https://www.sqlite.org/rescode.html#mismatch]
        try {
            if ($object = $stmt->execute()) {
                $this->prepared[$reference]['result'] = $object;
            }
        } catch (\Exception $e) {
            return false;
        }

        return ($object) ? true : false; // returns (bool) true or false
    }

    protected function dbExecuteError($stmt)
    {
        return $this->dbPrepareError(); // returns (string) error or false
    }

    protected function dbStyle($fetch)
    {
        switch ($fetch) {
            case 'assoc':
                return \SQLITE3_ASSOC;
                break;
            case 'both':
                return \SQLITE3_BOTH;
                break;
            default:
                return \SQLITE3_NUM;
                break;
        }
    }

    protected function dbFetch($stmt, $style, $reference)
    {
        return (isset($this->prepared[$reference]['result'])) ? $this->prepared[$reference]['result']->fetchArray($style) : false; // returns (mixed) $style or false
    }

    protected function dbInserted()
    {
        return $this->connection->lastInsertRowID(); // returns (int) last inserted row id or sequence value
    }

    protected function dbAffected($stmt)
    {
        return $this->connection->changes(); // returns (int) number of rows affected by last $stmt
    }

    protected function dbClose($stmt, $reference)
    {
        if (isset($this->prepared[$reference]['result'])) {
            $this->prepared[$reference]['result']->finalize();
            $this->prepared[$reference]['result'] = null;
        }

        return $stmt->close(); // returns (bool) true or false
    }

    protected function dbEscape($string)
    {
        return (is_numeric($string)) ? $string : "'".$this->connection->escapeString($string)."'";
    }
}


<?php

/*
 * This file is part of the slince/upload package.
 *
 * (c) Slince <taosikai@yeah.net>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Slince\Upload\Filesystem;

use Symfony\Component\HttpFoundation\File\UploadedFile;

class Local implements FilesystemInterface
{
    /**
     * @var string
     */
    protected $savePath;

    public function __construct($savePath)
    {
        if (!is_dir($savePath)) {
            throw new \InvalidArgumentException(sprintf('The directory "%s" is invalid', $savePath));
        }
        $this->savePath = rtrim($savePath, '\\/');
    }

    /**
     * {@inheritdoc}
     */
    public function upload($key, UploadedFile $file, $overwrite = false)
    {
        $filePath = $this->getFilePath($key);
        if (file_exists($filePath) && !$overwrite) {
            throw new \RuntimeException(sprintf('The file with key "%s" is exists.', $key));
        }
        return $file->move(dirname($filePath), basename($filePath));
    }

    protected function getFilePath($key)
    {
        return "{$this->savePath}/{$key}";
    }
}


<?php

namespace ParameterParser;

use Closure;
use ReflectionFunction;

class ParameterClosure
{
    /**
     * The name of the parameter.
     *
     * @var string
     */
    public $parameterName;

    /**
     * The closure to associate with the parameter.
     *
     * @var Closure
     */
    public $parameterClosure;

    /**
     * The aliases for the parameter.
     *
     * @var array
     */
    public $aliases = [];

    /**
     * The parent ParameterClosure if this object is registered
     * as an alias ParameterClosure object.
     *
     * @var ParameterClosure
     */
    public $parent;

    /**
     * The description of the parameter.
     *
     * @var string
     */
    public $description;

    /**
     * The prefix to associate with this parameter.
     *
     * @var string
     */
    public $prefix;

    /**
     * If set to true, the parameter will be required.
     * @var bool
     */
    public $required = false;

    /**
     * Construct the ParameterClosure with a name and closure.
     *
     * @param string  $prefix
     * @param string  $parameterName
     * @param Closure $parameterClosure
     * @param bool    $required
     */
    public function __construct(
        $prefix,
        $parameterName,
        Closure $parameterClosure,
        $required = false
    ) {
        $this->parameterName = $parameterName;
        $this->parameterClosure = $parameterClosure;
        $this->prefix = $prefix;
        $this->required = $required;
    }

    /**
     * Gets the usage of the ParameterClosure as string.
     *
     * @param bool $withEncapsulation
     * @param bool $withAliases
     *
     * @return string
     */
    public function getUsage($withEncapsulation = true, $withAliases = true)
    {
        $usage = '';
        if ($withEncapsulation) {
            $usage = ($this->required ? '' : '[');
        }
        $aliases = ($withAliases ? $this->getAliasUsage() : '');

        $usage .= $this->prefix.$this->parameterName.$aliases.' ';

        $usage .= $this->getPropertiesAsString();

        return $usage.($withEncapsulation ? ($this->required ? '' : ']') : '');
    }

    /**
     * Retrieve the properties for this parameter as a string.
     *
     * @return string
     */
    public function getPropertiesAsString()
    {
        $result = '';

        $rFunction = new ReflectionFunction($this->parameterClosure);
        if ($rFunction->isVariadic()) {
            $result .= '<'.
            $rFunction->getParameters()[0]->getName().', ...>';
        } else {
            for ($i = 0; $i < count($rFunction->getParameters()); $i++) {
                $result .= ($result == '' ? '' : ' ').'<'.
                $rFunction->getParameters()[$i]->getName().
                '>';
            }
        }

        return $result;
    }

    /**
     * Retrieve the alias usage as a String.
     *
     * @return string
     */
    public function getAliasUsage($withEncapsulation = true)
    {
        $aliases = '';

        foreach ($this->aliases as $prefix => $alias) {
            if ($withEncapsulation) {
                $aliases = ($aliases == '') ? ' (' : $aliases;
                $aliases .= ' '.$prefix.$alias;
            } else {
                $aliases = ($aliases == '') ? $prefix.$alias : $aliases.', '.$prefix.$alias;
            }
        }

        if ($withEncapsulation) {
            $aliases .= ($aliases == '') ? '' : ' )';
        }

        return $aliases;
    }

    /**
     * Set the description for the ParameterParser.
     *
     * @param string $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * Add an alias and associate it with a prefix.
     * If no prefix is defined, the default for
     * the cluster will be used.
     *
     * Only one alias can exist per prefix per parameter.
     *
     * @param string $parameterName
     * @param string $prefix
     */
    public function addAlias($parameterName, $prefix = null)
    {
        if ($prefix == null) {
            $this->aliases[$this->prefix] = $parameterName;
        } else {
            $this->aliases[$prefix] = $parameterName;
        }
    }

    /**
     * Return true if this object is a Parent ParameterClosure.
     *
     * @return bool
     */
    public function isParent()
    {
        return $this->parent != null;
    }
}


<?php namespace LasseRafn\CvrApi;

use LasseRafn\CvrApi\Models\Business;
use LasseRafn\CvrApi\Utils\Request;

class CvrApi
{
	protected $request;

	public function __construct()
	{
		$this->request = new Request(config( 'cvrapi.endpoint' ));
	}

	/**
	 * @param string $query
	 * @param string $country
	 *
	 * @return Business
	 */
	public function get($query = '', $country = 'dk')
	{
		$response = $this->request->get($query, $country);

		// todo throw error if... has error...

		return new Business($response);
	}
}


<?php
/*
 * This file licensed under the MIT license.
 *
 * (c) Sylvain Mauduit <sylvain@mauduit.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Swop\GitHubWebHook\Event;

use Psr\Http\Message\RequestInterface;
use Swop\GitHubWebHook\Exception\InvalidGitHubRequestPayloadException;
use Swop\GitHubWebHook\Exception\MissingGitHubEventTypeException;

/**
 * Factory implementation which handle the GitHub event creation
 *
 * @author Sylvain Mauduit <sylvain@mauduit.fr>
 */
class GitHubEventFactory implements GitHubEventFactoryInterface
{
    /**
     * {@inheritdoc}
     */
    public function build($type, array $payload)
    {
        return new GitHubEvent($type, $payload);
    }

    /**
     * {@inheritdoc}
     */
    public function buildFromRequest(RequestInterface $request)
    {
        $eventType = $request->getHeader('X-GitHub-Event');

        if (count($eventType) > 0) {
            $eventType = current($eventType);
        } else {
            throw new MissingGitHubEventTypeException($request);
        }

        $body = $request->getBody();
        $body->rewind();
        $body = $body->getContents();

        $payload = json_decode($body, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new InvalidGitHubRequestPayloadException($request, $body);
        }

        return $this->build($eventType, $payload);
    }
}


<?php
/**
 * This file is part of the proophsoftware/postgres-document-store.
 * (c) %year% prooph software GmbH <contact@prooph.de>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types=1);

namespace Prooph\EventMachine\Postgres;

use Prooph\EventMachine\Persistence\DocumentStore;
use Prooph\EventMachine\Persistence\DocumentStore\Filter\Filter;
use Prooph\EventMachine\Persistence\DocumentStore\Index;
use Prooph\EventMachine\Persistence\DocumentStore\OrderBy\OrderBy;
use Prooph\EventMachine\Postgres\Exception\InvalidArgumentException;
use Prooph\EventMachine\Postgres\Exception\RuntimeException;

final class PostgresDocumentStore implements DocumentStore
{
    /**
     * @var \PDO
     */
    private $connection;

    private $tablePrefix = 'em_ds_';

    private $docIdSchema = 'UUID NOT NULL';

    private $manageTransactions;

    public function __construct(
        \PDO $connection,
        string $tablePrefix = null,
        string $docIdSchema = null,
        bool $transactional = true
    ) {
        $this->connection = $connection;
        $this->connection->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

        if(null !== $tablePrefix) {
            $this->tablePrefix = $tablePrefix;
        }

        if(null !== $docIdSchema) {
            $this->docIdSchema = $docIdSchema;
        }

        $this->manageTransactions = $transactional;
    }

    /**
     * @return string[] list of all available collections
     */
    public function listCollections(): array
    {
        $prefix = mb_strtolower($this->tablePrefix);
        $query = <<<EOT
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME LIKE '{$prefix}%'
EOT;

        $stmt = $this->connection->prepare($query);

        $stmt->execute();

        $collections = [];

        while ($col = $stmt->fetchColumn()) {
            $collections[] = str_replace($prefix, '', $col);
        }

        return $collections;
    }

    /**
     * @param string $prefix
     * @return string[] of collection names
     */
    public function filterCollectionsByPrefix(string $prefix): array
    {
        $tPrefix = mb_strtolower($this->tablePrefix);
        $prefix = mb_strtolower($prefix);
        $query = <<<EOT
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME LIKE '{$tPrefix}$prefix%'
EOT;

        $stmt = $this->connection->prepare($query);

        $stmt->execute();

        $collections = [];

        while ($col = $stmt->fetchColumn()) {
            $collections[] = str_replace($tPrefix, '', $col);
        }

        return $collections;
    }

    /**
     * @param string $collectionName
     * @return bool
     */
    public function hasCollection(string $collectionName): bool
    {
        $query = <<<EOT
SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME = '{$this->tableName($collectionName)}'
EOT;

        $stmt = $this->connection->prepare($query);

        $stmt->execute();

        $row = $stmt->fetchColumn();

        return !!$row;
    }

    /**
     * @param string $collectionName
     * @param Index[] ...$indices
     */
    public function addCollection(string $collectionName, Index ...$indices): void
    {
        $cmd = <<<EOT
CREATE TABLE {$this->tableName($collectionName)} (
    id {$this->docIdSchema},
    doc JSONB NOT NULL,
    PRIMARY KEY (id)
);
EOT;

        $indicesCmds = array_map(function (Index $index) use ($collectionName) {
            return $this->indexToSqlCmd($index, $collectionName);
        }, $indices);

        $this->transactional(function() use ($cmd, $indicesCmds) {
            $this->connection->prepare($cmd)->execute();

            array_walk($indicesCmds, function ($cmd) {
                $this->connection->prepare($cmd)->execute();
            });
        });
    }

    /**
     * @param string $collectionName
     * @throws \Throwable if dropping did not succeed
     */
    public function dropCollection(string $collectionName): void
    {
        $cmd = <<<EOT
DROP TABLE {$this->tableName($collectionName)};
EOT;

        $this->transactional(function () use ($cmd) {
            $this->connection->prepare($cmd)->execute();
        });
    }

    /**
     * @param string $collectionName
     * @param string $docId
     * @param array $doc
     * @throws \Throwable if adding did not succeed
     */
    public function addDoc(string $collectionName, string $docId, array $doc): void
    {
        $cmd = <<<EOT
INSERT INTO {$this->tableName($collectionName)} (id, doc) VALUES (:id, :doc);
EOT;
        $this->transactional(function () use ($cmd, $docId, $doc) {
            $this->connection->prepare($cmd)->execute([
                'id' => $docId,
                'doc' => json_encode($doc)
            ]);
        });
    }

    /**
     * @param string $collectionName
     * @param string $docId
     * @param array $docOrSubset
     * @throws \Throwable if updating did not succeed
     */
    public function updateDoc(string $collectionName, string $docId, array $docOrSubset): void
    {
        $cmd = <<<EOT
UPDATE {$this->tableName($collectionName)}
SET doc = (to_jsonb(doc) || :doc)
WHERE id = :id
;
EOT;
        $this->transactional(function () use ($cmd, $docId, $docOrSubset) {
            $this->connection->prepare($cmd)->execute([
                'id' => $docId,
                'doc' => json_encode($docOrSubset)
            ]);
        });
    }

    /**
     * @param string $collectionName
     * @param Filter $filter
     * @param array $set
     * @throws \Throwable in case of connection error or other issues
     */
    public function updateMany(string $collectionName, Filter $filter, array $set): void
    {
        [$filterStr, $args] = $this->filterToWhereClause($filter);

        $where = $filterStr? "WHERE $filterStr" : '';

        $cmd = <<<EOT
UPDATE {$this->tableName($collectionName)}
SET doc = (to_jsonb(doc) || :doc)
$where;
EOT;

        $args['doc'] = json_encode($set);

        $this->transactional(function () use ($cmd, $args) {
            $this->connection->prepare($cmd)->execute($args);
        });
    }

    /**
     * Same as updateDoc except that doc is added to collection if it does not exist.
     *
     * @param string $collectionName
     * @param string $docId
     * @param array $docOrSubset
     * @throws \Throwable if insert/update did not succeed
     */
    public function upsertDoc(string $collectionName, string $docId, array $docOrSubset): void
    {
        $doc = $this->getDoc($collectionName, $docId);

        if($doc) {
            $this->updateDoc($collectionName, $docId, $docOrSubset);
        } else {
            $this->addDoc($collectionName, $docId, $docOrSubset);
        }
    }

    /**
     * @param string $collectionName
     * @param string $docId
     * @throws \Throwable if deleting did not succeed
     */
    public function deleteDoc(string $collectionName, string $docId): void
    {
        $cmd = <<<EOT
DELETE FROM {$this->tableName($collectionName)}
WHERE id = :id
EOT;

        $this->transactional(function () use ($cmd, $docId) {
            $stmt = $this->connection->prepare($cmd);

            $stmt->execute(['id' => $docId]);
        });
    }

    /**
     * @param string $collectionName
     * @param Filter $filter
     * @throws \Throwable in case of connection error or other issues
     */
    public function deleteMany(string $collectionName, Filter $filter): void
    {
        [$filterStr, $args] = $this->filterToWhereClause($filter);

        $where = $filterStr? "WHERE $filterStr" : '';

        $cmd = <<<EOT
DELETE FROM {$this->tableName($collectionName)}
$where;
EOT;

        $this->transactional(function () use ($cmd, $args) {
            $this->connection->prepare($cmd)->execute($args);
        });
    }

    /**
     * @param string $collectionName
     * @param string $docId
     * @return array|null
     */
    public function getDoc(string $collectionName, string $docId): ?array
    {
        $query = <<<EOT
SELECT doc
FROM {$this->tableName($collectionName)}
WHERE id = :id
EOT;
        $stmt = $this->connection->prepare($query);

        $stmt->execute(['id' => $docId]);

        $row = $stmt->fetchColumn();

        if(!$row) {
            return null;
        }

        return json_decode($row, true);
    }

    /**
     * @param string $collectionName
     * @param Filter $filter
     * @param int|null $skip
     * @param int|null $limit
     * @param OrderBy|null $orderBy
     * @return \Traversable list of docs
     */
    public function filterDocs(string $collectionName, Filter $filter, int $skip = null, int $limit = null, OrderBy $orderBy = null): \Traversable
    {
        [$filterStr, $args] = $this->filterToWhereClause($filter);

        $where = $filterStr? "WHERE $filterStr" : '';

        $offset = $skip !== null ? "OFFSET $skip" : '';
        $limit = $limit !== null ? "LIMIT $limit" : '';

        $orderBy = $orderBy ? "ORDER BY " . implode(', ', $this->orderByToSort($orderBy)) : '';

        $query = <<<EOT
SELECT doc
FROM {$this->tableName($collectionName)}
$where
$orderBy
$limit
$offset;
EOT;
        $stmt = $this->connection->prepare($query);

        $stmt->execute($args);

        while($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
            yield json_decode($row['doc'], true);
        }
    }

    private function transactional(callable $callback)
    {
        if($this->manageTransactions) {
            $this->connection->beginTransaction();
        }

        try {
            $callback();
            if($this->manageTransactions) {
                $this->connection->commit();
            }
        } catch (\Throwable $exception) {
            if($this->manageTransactions) {
                $this->connection->rollBack();
            }
            throw $exception;
        }
    }

    private function filterToWhereClause(Filter $filter, $argsCount = 0): array
    {
        if($filter instanceof DocumentStore\Filter\AnyFilter) {
            if($argsCount > 0) {
                throw new InvalidArgumentException('AnyFilter cannot be used together with other filters.');
            }
            return [null, [], $argsCount];
        }

        if($filter instanceof DocumentStore\Filter\AndFilter) {
            [$filterA, $argsA, $argsCount] = $this->filterToWhereClause($filter->aFilter(), $argsCount);
            [$filterB, $argsB, $argsCount] = $this->filterToWhereClause($filter->bFilter(), $argsCount);
            return ["($filterA AND $filterB)", array_merge($argsA, $argsB), $argsCount];
        }

        if($filter instanceof DocumentStore\Filter\OrFilter) {
            [$filterA, $argsA, $argsCount] = $this->filterToWhereClause($filter->aFilter(), $argsCount);
            [$filterB, $argsB, $argsCount] = $this->filterToWhereClause($filter->bFilter(), $argsCount);
            return ["($filterA OR $filterB)", array_merge($argsA, $argsB), $argsCount];
        }

        switch (get_class($filter)) {
            case DocumentStore\Filter\EqFilter::class:
                /** @var DocumentStore\Filter\EqFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop = :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\GtFilter::class:
                /** @var DocumentStore\Filter\GtFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop > :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\GteFilter::class:
                /** @var DocumentStore\Filter\GteFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop >= :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\LtFilter::class:
                /** @var DocumentStore\Filter\LtFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop < :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\LteFilter::class:
                /** @var DocumentStore\Filter\LteFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop <= :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\LikeFilter::class:
                /** @var DocumentStore\Filter\LikeFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                $propParts = explode('->', $prop);
                $lastProp = array_pop($propParts);
                $prop = implode('->', $propParts) . '->>'.$lastProp;
                return ["$prop LIKE :a$argsCount", ["a$argsCount" => $filter->val()], ++$argsCount];
            case DocumentStore\Filter\NotFilter::class:
                /** @var DocumentStore\Filter\NotFilter $filter */
                $innerFilter = $filter->innerFilter();

                if (!$this->isPropFilter($innerFilter)) {
                    throw new RuntimeException('Not filter cannot be combined with a non prop filter!');
                }

                [$innerFilterStr, $args, $argsCount] = $this->filterToWhereClause($innerFilter);

                return ["NOT $innerFilterStr", $args, $argsCount];
            case DocumentStore\Filter\InArrayFilter::class:
                /** @var DocumentStore\Filter\InArrayFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                return ["$prop @> :a$argsCount", ["a$argsCount" => json_encode($filter->val())], ++$argsCount];
            case DocumentStore\Filter\ExistsFilter::class:
                /** @var DocumentStore\Filter\ExistsFilter $filter */
                $prop = $this->propToJsonPath($filter->prop());
                $propParts = explode('->', $prop);
                $lastProp = trim(array_pop($propParts), "'");
                $parentProps = implode('->', $propParts);
                return ["JSONB_EXISTS($parentProps, '$lastProp')", [], $argsCount];
            default:
                throw new RuntimeException('Unsupported filter type. Got ' . get_class($filter));
        }
    }

    private function propToJsonPath(string $field): string
    {
        return "doc->'" . str_replace('.', "'->'", $field) . "'";
    }

    private function isPropFilter(Filter $filter): bool
    {
        switch (get_class($filter)) {
            case DocumentStore\Filter\AndFilter::class:
            case DocumentStore\Filter\OrFilter::class:
            case DocumentStore\Filter\NotFilter::class:
                return false;
            default:
                return true;
        }
    }

    private function orderByToSort(DocumentStore\OrderBy\OrderBy $orderBy): array
    {
        $sort = [];

        if($orderBy instanceof DocumentStore\OrderBy\AndOrder) {
            /** @var DocumentStore\OrderBy\Asc|DocumentStore\OrderBy\Desc $orderByA */
            $orderByA = $orderBy->a();
            $direction = $orderByA instanceof DocumentStore\OrderBy\Asc ? 'ASC' : 'DESC';
            $prop = $this->propToJsonPath($orderByA->prop());
            $sort[] = "{$prop} $direction";

            $sortB = $this->orderByToSort($orderBy->b());

            return array_merge($sort, $sortB);
        }

        /** @var DocumentStore\OrderBy\Asc|DocumentStore\OrderBy\Desc $orderBy */
        $direction = $orderBy instanceof DocumentStore\OrderBy\Asc ? 'ASC' : 'DESC';
        $prop = $this->propToJsonPath($orderBy->prop());
        return ["{$prop} $direction"];
    }

    private function indexToSqlCmd(Index $index, string $collectionName): string
    {
        if($index instanceof DocumentStore\FieldIndex) {
            $type = $index->unique() ? 'UNIQUE INDEX' : 'INDEX';
            $fields = '('.$this->extractFieldPartFromFieldIndex($index).')';
        } elseif ($index instanceof DocumentStore\MultiFieldIndex) {
            $type = $index->unique() ? 'UNIQUE INDEX' : 'INDEX';
            $fieldParts = array_map([$this, 'extractFieldPartFromFieldIndex'], $index->fields());
            $fields = '('.implode(', ', $fieldParts).')';
        } else {
            throw new RuntimeException('Unsupported index type. Got ' . get_class($index));
        }

        $cmd = <<<EOT
CREATE $type ON {$this->tableName($collectionName)}
$fields;
EOT;

        return $cmd;
    }

    private function extractFieldPartFromFieldIndex(DocumentStore\FieldIndex $fieldIndex): string
    {
        $direction = $fieldIndex->sort() === Index::SORT_ASC ? 'ASC' : 'DESC';
        $prop = $this->propToJsonPath($fieldIndex->field());
        return "($prop) $direction";
    }

    private function tableName(string $collectionName): string
    {
        return mb_strtolower($this->tablePrefix . $collectionName);
    }
}


<?php
/**
 * TravisDeployer
 *
 * @link      https://github.com/Enrise/TravisDeployer for the canonical source repository
 * @copyright Copyright (c) 2015 Enrise BV
 * @license   https://github.com/Enrise/TravisDeployer/blob/master/LICENSE GNU v3 License
 */
namespace Enrise\TravisDeployer;

use Symfony\Component\Yaml\Parser;

class TravisDeployer
{
    /**
     * @var array<string branch, string stage>
     */
    protected $branches;

    /**
     * @var bool
     */
    protected $verbose;

    /**
     * Load the config on init
     */
    public function __construct()
    {
        $this->getConfig();
    }

    /**
     * Parse the config and place them into protected variables
     */
    private function getConfig()
    {
        $yaml = new Parser();

        $configFile = getenv('TRAVIS_BUILD_DIR') . '/.travis.yml';

        $config = $yaml->parse(file_get_contents($configFile));
        $config = $config['travisdeployer'];

        $this->branches = $config['branches'];
        if (count($this->branches) === 0) {
            die('No branches are configured to deploy to.' . PHP_EOL);
        }

        $this->verbose = filter_input(FILTER_VALIDATE_BOOLEAN, $config['verbose']);
    }

    /**
     * Deploy to the configured branch
     */
    public function deploy()
    {
        $pullRequest = getenv('TRAVIS_PULL_REQUEST');
        $branch = getenv('TRAVIS_BRANCH');

        if ((int) $pullRequest >= 1) {
            die('Not deploying pull requests.' . PHP_EOL);
        }

        if (!array_key_exists($branch, $this->branches)) {
            die('Branch ' . $branch . ' has no environment to deploy to.' . PHP_EOL);
        }

        $environment = $this->branches[$branch];

        echo 'Downloading Deployer.phar...' . PHP_EOL;
        passthru('wget http://deployer.org/deployer.phar');

        echo 'Deploying...' . PHP_EOL;
        $deployCommand = 'php deployer.phar deploy';
        $deployCommand .= ' ' . $environment;
        $deployCommand .= $this->verbose ? ' -vvv' : '';
        passthru($deployCommand);
    }
}


<?php
/*
 * This file licensed under the MIT license.
 *
 * (c) Sylvain Mauduit <sylvain@mauduit.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Swop\GitHubWebHook\Security;

use Psr\Http\Message\RequestInterface;
use Swop\GitHubWebHook\Exception\InvalidGitHubRequestSignatureException;

/**
 * Signature validator implementation
 *
 * @see \Swop\GitHubWebHook\Security\SignatureValidatorInterface
 *
 * @author Sylvain Mauduit <sylvain@mauduit.fr>
 */
class SignatureValidator implements SignatureValidatorInterface
{
    /**
     * {@inheritdoc}
     */
    public function validate(RequestInterface $request, $secret)
    {
        $signature   = $request->getHeader('X-Hub-Signature');
        $requestBody = $request->getBody();
        $requestBody->rewind();

        $payload = $requestBody->getContents();

        if (!$this->validateSignature($signature, $payload, $secret)) {
            throw new InvalidGitHubRequestSignatureException($request, $signature);
        }
    }

    /**
     * @param string $signature
     * @param string $payload
     * @param string $secret
     *
     * @return bool
     */
    private function validateSignature($signature, $payload, $secret)
    {
        if (empty($signature)) {
            return false;
        }

        $signature = current($signature);

        $explodeResult = explode('=', $signature, 2);

        if (2 !== count($explodeResult)) {
            return false;
        }

        list($algorithm, $hash) = $explodeResult;

        if (empty($algorithm) || empty($hash)) {
            return false;
        }

        if (!in_array($algorithm, hash_algos())) {
            return false;
        }

        $payloadHash = hash_hmac($algorithm, $payload, $secret);

        return $hash === $payloadHash;
    }
}


<?php

namespace ParameterParser;

use Closure;
use ReflectionFunction;

class ParameterParser
{
    /**
     * The constant value that is used to halt the parser.
     */
    public const HALT_PARSE = 'parameter_parser_halt_parser';

    /**
     * The array of arguments to use.
     *
     * @var array
     */
    private $argv;

    /**
     * The parameter cluster to use for parsing arguments to closures.
     *
     * @var array
     */
    private $parameterCluster = null;

    /**
     * The validity of the parsed parameters.
     *
     * @var bool
     */
    private $valid = true;

    /**
     * The error handler closure.
     *
     * @var Closure
     */
    private $errorHandler;

    /**
     * If a parameter halts the execution fot he parser,
     * it will be stored here.
     *
     * @var string
     */
    private $haltedBy = null;

    /**
     * Construct the Parameter Parser using an array of arguments.
     *
     * @param array            $argv
     * @param ParameterCluster $prefixes
     */
    public function __construct(
        $argv = null,
        ParameterCluster $parameterCluster = null
    ) {
        $this->parameterCluster = new ParameterCluster();
        $this->errorHandler = function (
            ParameterClosure $parameterClosure,
            $errorMessage
        ) {
            // Empty Error Handler
        };
        $this->initialize($argv, $parameterCluster);
    }

    /**
     * Parse the arguments.
     *
     * @param array            $argv
     * @param ParameterCluster $parameterCluster
     *
     * @return array
     */
    public function parse(
        $argv = null,
        ParameterCluster $parameterCluster = null
    ) {
        $this->initialize($argv, $parameterCluster);

        return $this->checkValidityAndContinueParse();
    }

    /**
     * Sets an error handler for the ParameterParser.
     *
     * @param Closure $closure
     */
    public function setErrorHandler(Closure $closure)
    {
        $this->errorHandler = $closure;
    }

    /**
     * Sets the default closure.
     *
     * @param Closure $closure
     */
    public function setDefault(Closure $closure)
    {
        $this->parameterCluster->setDefault($closure);
    }

    /**
     * Check if the parsed parameters are valid.
     *
     * @return bool
     */
    public function isValid()
    {
        return $this->valid;
    }

    /**
     * Retrieves the parameter that halted the execution
     * of the parser, if any. If the parser was not halted
     * null will be returned.
     *
     * @return \ParameterParser\ParameterClosure
     */
    public function haltedBy()
    {
        return $this->haltedBy;
    }

    /**
     * Retrieves the name of the parameter that halted the execution
     * of the parser, if any. If the parser was not halted
     * null will be returned.
     *
     * @return \ParameterParser\ParameterClosure
     */
    public function haltedByName()
    {
        return ($this->haltedBy == null)
            ? null
            : $this->haltedBy->parameterName;
    }

    /**
     * Validates the parameters passed to the initializer
     * and continues the parse if it sees fit.
     *
     * @return array
     */
    private function checkValidityAndContinueParse()
    {
        $valid = $this->validateRequiredParameters();
        if ($valid !== true) {
            $this->errorHandler->call(
                $this,
                $valid,
                'Missing required argument: '.$valid->parameterName
            );
            $this->valid = false;

            return [];
        }

        return $this->parseEvery();
    }

    /**
     * Parse every element in the loaded parameters.
     *
     * @return array
     */
    private function parseEvery()
    {
        $results = [];

        $i = 0;
        while ($i < count($this->argv)) {
            $parameter = $this->argv[$i];
            if ($this->parseSingle($i, $parameter, $results) === false) {
                break;
            }
        }

        return $results;
    }

    /**
     * Parse a single parameter and increment the parser.
     *
     * If this function returns 'false', it means that
     * the parse was halted by one of the parameters.
     *
     * @param int    &$i
     * @param string  $parameter
     * @param array  &$results
     *
     * @return bool
     */
    private function parseSingle(&$i, $parameter, &$results)
    {
        if ($this->prefixExists($parameter)) {
            $closure = $this->getClosure($parameter);

            if ($closure != null) {
                $prefix = $this->getPrefix($parameter);
                $closure_arguments = [];
                $rFunction = new ReflectionFunction($closure);
                if ($rFunction->isVariadic()) {
                    $this->parseVariadicParameter(
                        $i,
                        $results,
                        $closure,
                        $closure_arguments,
                        $prefix,
                        $parameter
                    );
                } else {
                    $this->parseUniadicParameter(
                        $i,
                        $results,
                        $closure,
                        $closure_arguments,
                        $prefix,
                        $parameter,
                        $rFunction
                    );
                }

                $result_key = $this->getRealName($parameter);
                $result = $results[$result_key];

                if (! $result instanceof ParameterResult) {
                    if ($result == self::HALT_PARSE) {
                        $this->haltedBy = $this->getParameterClosure($parameter);
                        unset($results[$result_key]);

                        return false;
                    }
                } else {
                    if ($result->shouldHalt()) {
                        $this->haltedBy = $this->getParameterClosure($parameter);
                        if ($result->isHaltOnly()) {
                            unset($results[$result_key]);
                        } else {
                            $results[$result_key] = $result->getValue();
                        }

                        return false;
                    }
                }
            } else {
                $this->respondDefault($i, $results, $parameter);
            }
        } else {
            $this->respondDefault($i, $results, $parameter);
        }

        return true;
    }

    /**
     * Validates the parameter list by verifying that it contains
     * all required parameters. Returns the ParameterClosure if a parameter
     * is missing, else it will return true.
     *
     * @return mixed
     */
    private function validateRequiredParameters()
    {
        $ret = true;
        foreach ($this->parameterCluster->prefixes as $prefix => $parameters) {
            foreach ($parameters as $parameterClosure) {
                if ($parameterClosure->required) {
                    if (! in_array(
                        $parameterClosure
                        ->prefix.
                        $parameterClosure
                        ->parameterName,
                        $this->argv
                    )) {
                        $aliasFound = false;
                        foreach ($parameterClosure->aliases as $prefix => $alias) {
                            if (in_array($prefix.$alias, $this->argv)) {
                                $aliasFound = true;
                                break;
                            }
                        }
                        if (! $aliasFound) {
                            $ret = $parameterClosure;
                            break 2;
                        }
                    }
                }
            }
        }

        return $ret;
    }

    /**
     * Initialize the ParameterParser with new data.
     *
     * @param  array            $argv
     * @param  ParameterCluster $parameterCluster
     */
    private function initialize($argv, $parameterCluster)
    {
        $this->valid = true;
        $this->haltedBy = null;
        if ($parameterCluster != null) {
            $this->parameterCluster = $parameterCluster;
            if ($argv != null) {
                $this->preloadAliases($argv);
            }
        }

        if ($argv != null) {
            $this->preloadParameters($argv);
        }
    }

    /**
     * Parses the parameter with the default closure and increments
     * the parameter parser. If '-1' is returned by the default
     * closure, the parameters will be invalidated.
     *
     * @param  int    &$i
     * @param  array  &$results
     * @param  string $parameter
     */
    private function respondDefault(&$i, &$results, $parameter)
    {
        $defaultResult = $this->parameterCluster->default->call(
            $this, $parameter
        );

        if ($defaultResult === -1) {
            $this->valid = false;
        }

        $results[$parameter] = $defaultResult;
        $i++;
    }

    /**
     * Preload alias ParameterClosures into the system.
     */
    private function preloadAliases()
    {
        foreach (array_keys($this->parameterCluster->prefixes) as $prefix) {
            foreach (
                $this->parameterCluster->prefixes[$prefix] as $parameterClosure
            ) {
                foreach ($parameterClosure->aliases as $prefix => $alias) {
                    $aliasClosure = new ParameterClosure(
                        $prefix,
                        $alias,
                        $parameterClosure->parameterClosure
                    );
                    $aliasClosure->parent = $parameterClosure;
                    $this->parameterCluster->add(
                        $aliasClosure
                    );
                }
            }
        }
    }

    /**
     * Preloads the parameters and moves any parameters surrounded by
     * single or double quotes to their own parameter.
     *
     * @param  array $argv
     */
    private function preloadParameters($argv)
    {
        array_shift($argv);
        $this->argv = [];

        while (($argument = array_shift($argv)) != null) {
            switch (substr($argument, 0, 1)) {
                case '\'': {
                    $this->parseQuote($argv, $argument, '\'');
                    break;
                }

                case '"': {
                    $this->parseQuote($argv, $argument, '"');
                    break;
                }

                default: {
                    $this->argv[] = $argument;
                }
            }
        }
    }

    /**
     * Parse all parameters between two matching single or double quotes
     * to a single element in the parameter array.
     *
     * @param  array  &$argv
     * @param  string $argument
     * @param  string $quoteType
     */
    private function parseQuote(&$argv, $argument, $quoteType)
    {
        if (substr($argument, strlen($argument) - 1, 1) !== $quoteType) {
            $this->argv[] = substr($argument, 1);
            while (
                ($argument_part = array_shift($argv)) != null
                && substr(
                    $argument_part,
                    strlen($argument_part) - 1,
                    1
                ) !== $quoteType
            ) {
                $this->argv[count($this->argv) - 1] .= ' '.$argument_part;
            }
            $this->argv[count($this->argv) - 1] .=
            ' '.substr($argument_part, 0, strlen($argument_part) - 1);
        } else {
            $this->argv[] = substr(
                substr(
                    $argument,
                    1
                ),
                0,
                strlen($argument) - 2
            );
        }
    }

    /**
     * Parse a parameter belonging to a prefix that has a non-variadic
     * (or uniadic) structure in it's closure definition and increment
     * the parameter parser.
     *
     * @param  int                &$i
     * @param  array              &$results
     * @param  Closure            $closure
     * @param  array              &$closure_arguments
     * @param  string             $prefix
     * @param  string             $parameter
     * @param  ReflectionFunction $rFunction
     */
    private function parseUniadicParameter(
        &$i,
        &$results,
        $closure,
        &$closure_arguments,
        $prefix,
        $parameter,
        $rFunction
    ) {
        $current_argument = 0;
        $argument_count = count($rFunction->getParameters());
        while (
            $current_argument < $argument_count &&
            count($this->argv) > ($i + 1)
        ) {
            $closure_arguments[] = $this->argv[$i + 1];
            $current_argument += 1;
            $i++;
        }
        $parameterClosure = $this->getParameterClosure($parameter);
        if ($parameterClosure->parent != null) {
            if (count($closure_arguments) == $argument_count) {
                $results[
                    $parameterClosure->parent->parameterName
                ] = $closure(...$closure_arguments);
            } else {
                $this->valid = false;
                if ($this->errorHandler != null) {
                    $this->errorHandler->call(
                        $this,
                        $parameterClosure,
                        'Invalid argument count for parameter closure.'
                    );
                }
            }
        } else {
            if (count($closure_arguments) == $argument_count) {
                $results[
                    substr(
                        $parameter,
                        strlen($prefix),
                        strlen($parameter) - strlen($prefix)
                    )
                ] = $closure(...$closure_arguments);
            } else {
                $this->valid = false;
                if ($this->errorHandler != null) {
                    $this->errorHandler->call(
                        $this,
                        $parameterClosure,
                        'Invalid argument count for parameter closure.'
                    );
                }
            }
        }
        $i++;
    }

    /**
     * Parse a parameter belonging to a prefix that has a variadic
     * structure in it's closure definition and increment the
     * parameter parser.
     *
     * @param  int                &$i
     * @param  array              &$results
     * @param  Closure            $closure
     * @param  array              &$closure_arguments
     * @param  string             $prefix
     * @param  string             $parameter
     */
    private function parseVariadicParameter(
        &$i,
        &$results,
        $closure,
        &$closure_arguments,
        $prefix,
        $parameter
    ) {
        $i++;
        while (
            isset($this->argv[$i]) &&
            ($argument = $this->argv[$i]) != null &&
            ! $this->prefixExists($argument)
        ) {
            $closure_arguments[] = $argument;
            $i++;
        }
        $parameterClosure = $this->getParameterClosure($parameter);
        if ($parameterClosure->parent != null) {
            if (count($closure_arguments) > 0) {
                $results[
                    $parameterClosure->parent->parameterName
                ] = $closure(...$closure_arguments);
            } else {
                $this->valid = false;
                if ($this->errorHandler != null) {
                    $this->errorHandler->call(
                        $this,
                        $parameterClosure,
                        'Missing argument for parameter closure.'
                    );
                }
            }
        } else {
            if (count($closure_arguments) > 0) {
                $results[
                    substr(
                        $parameter,
                        strlen($prefix),
                        strlen($parameter) - strlen($prefix)
                    )
                ] = $closure(...$closure_arguments);
            } else {
                $this->valid = false;
                if ($this->errorHandler != null) {
                    $this->errorHandler->call(
                        $this,
                        $parameterClosure,
                        'Missing argument for parameter closure.'
                    );
                }
            }
        }
    }

    /**
     * Check if the prefix is defined in the parameter cluster.
     *
     * @param string $parameter
     *
     * @return bool
     */
    private function prefixExists($parameter)
    {
        $prefixExists = false;

        foreach (array_keys($this->parameterCluster->prefixes) as $prefix) {
            if (substr($parameter, 0, strlen($prefix)) == $prefix) {
                $prefixExists = true;
                break;
            }
        }

        return $prefixExists;
    }

    /**
     * Attempts to find the prefix associated with the parameter.
     * If no prefix is found, null will be returned.
     *
     * @param string $parameter
     *
     * @return string
     */
    private function getPrefix($parameter)
    {
        $prefix = null;

        foreach (array_keys($this->parameterCluster->prefixes) as $_prefix) {
            if (substr($parameter, 0, strlen($_prefix)) == $_prefix) {
                $prefix = $_prefix;
            }
        }

        return $prefix;
    }

    /**
     * Retrieves the real name that will be displayed in
     * the results for a parameter.
     *
     * @return string
     */
    private function getRealName($param)
    {
        $parameterClosure = $this->getParameterClosure($param);
        if ($parameterClosure->parent != null) {
            return $parameterClosure->parent->parameterName;
        } else {
            return $parameterClosure->parameterName;
        }
    }

    /**
     * Attempts to find the closure associated with the parameter
     * based on prefix. If no prefix is found, null will be returned.
     *
     * @param string $parameter
     *
     * @return Closure
     */
    private function getClosure($parameter)
    {
        $closure = null;

        foreach (array_keys($this->parameterCluster->prefixes) as $prefix) {
            if (substr($parameter, 0, strlen($prefix)) == $prefix) {
                @$closure = $this->parameterCluster->prefixes[$prefix][
                    substr(
                        $parameter,
                        strlen($prefix),
                        strlen($parameter) - strlen($prefix)
                    )
                ]->parameterClosure;
            }
        }

        return $closure;
    }

    /**
     * Get the ParameterClosure object associated with a parameter.
     * If no ParameterClosure is found for the parameter, return null.
     *
     * @param  string $parameter
     *
     * @return ParameterClosure
     */
    private function getParameterClosure($parameter)
    {
        $parameterClosure = null;

        foreach (array_keys($this->parameterCluster->prefixes) as $prefix) {
            if (substr($parameter, 0, strlen($prefix)) == $prefix) {
                @$parameterClosure = $this->parameterCluster->prefixes[$prefix][
                    substr(
                        $parameter,
                        strlen($prefix),
                        strlen($parameter) - strlen($prefix)
                    )
                ];
            }
        }

        return $parameterClosure;
    }
}


<?php

namespace Keboola\Syrup;

use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\MessageFormatter;
use GuzzleHttp\Middleware;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use GuzzleHttp\Client as GuzzleClient;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Log\LoggerInterface;

/**
 * Class Client
 * @package Keboola\Orchestrator
 */
class Client
{
    const DEFAULT_API_URL = 'https://syrup.keboola.com';
    const DEFAULT_USER_AGENT = 'Keboola Syrup PHP Client';
    const DEFAULT_BACKOFF_RETRIES = 11;

    protected $jobFinishedStates = ["cancelled", "canceled", "success", "error", "terminated"];

    /**
     * @var int Maximum delay between queries for job state
     */
    protected $maxDelay = 10;

    /**
     * @var string Name of parent component
     */
    protected $super = '';

    /**
     * @var string Actual base request URL.
     */
    private $url;

    /**
     * @var Actual base request URL for queue
     */
    private $queueUrl;

    /**
     * GuzzleClient
     */
    protected $guzzle;

    /**
     * @param int $maxRetries
     * @return \Closure
     */
    private static function createDefaultDecider($maxRetries = 3)
    {
        return function (
            $retries,
            RequestInterface $request,
            ResponseInterface $response = null,
            $error = null
        ) use ($maxRetries) {
            if ($retries >= $maxRetries) {
                return false;
            } elseif ($response && $response->getStatusCode() > 499) {
                return true;
            } elseif ($error) {
                return true;
            } else {
                return false;
            }
        };
    }

    /**
     * Create a client instance
     *
     * @param array $config Client configuration settings:
     *     - token: (optional) Storage API token.
     *     - runId: (optional) Storage API runId.
     *     - url: (optional) Syrup API URL to override the default (DEFAULT_API_URL).
     *     - super: (optional) Name of parent component if any.
     *     - userAgent: (optional) Custom user agent (appended to the default).
     *     - backoffMaxTries: (optional) Number of retries in case of backend error.
     *     - logger: (optional) instance of Psr\Log\LoggerInterface.
     *     - handler: (optional) instance of GuzzleHttp\HandlerStack.
     * @param callable $delay Optional custom delay method to apply (default is exponential)
     * @return Client
     * @deprecated
     */
    public static function factory(array $config = [], callable $delay = null)
    {
        return new self($config, $delay);
    }

    /**
     * Create a client instance
     *
     * @param array $config Client configuration settings:
     *     - token: (optional) Storage API token.
     *     - runId: (optional) Storage API runId.
     *     - url: (optional) Syrup API URL to override the default (DEFAULT_API_URL).
     *     - super: (optional) Name of parent component if any.
     *     - userAgent: (optional) Custom user agent (appended to the default).
     *     - backoffMaxTries: (optional) Number of retries in case of backend error.
     *     - logger: (optional) instance of Psr\Log\LoggerInterface.
     *     - handler: (optional) instance of GuzzleHttp\HandlerStack.
     * @param callable $delay Optional custom delay method to apply (default is exponential)
     * @return Client
     */
    public function __construct(array $config = [], callable $delay = null)
    {
        $token = '';

        if (!empty($config['token'])) {
            $token = $config['token'];
        }

        $apiUrl = self::DEFAULT_API_URL;
        if (!empty($config['url'])) {
            $apiUrl = $config['url'];
        }
        $this->setUrl($apiUrl);

        if (!empty($config['queueUrl'])) {
            $this->setQueueUrl($config['queueUrl']);
        } else {
            $this->setQueueUrl($apiUrl);
        }

        $runId = '';
        if (!empty($config['runId'])) {
            $runId = $config['runId'];
        }

        $userAgent = self::DEFAULT_USER_AGENT;
        if (!empty($config['userAgent'])) {
            $userAgent .= ' - ' . $config['userAgent'];
        }

        $maxRetries = self::DEFAULT_BACKOFF_RETRIES;
        if (!empty($config['backoffMaxTries'])) {
            $maxRetries = $config['backoffMaxTries'];
        }

        $this->guzzle = $this->initClient(
            $token,
            $runId,
            $userAgent,
            $maxRetries,
            $config,
            $delay
        );

        if (!empty($config['super'])) {
            $this->setSuper($config['super']);
        }
    }

    /**
     * @param $token
     * @param $runId
     * @param $userAgent
     * @param $maxRetries
     * @param array $config
     * @param callable|null $delay
     * @return GuzzleClient
     */
    protected function initClient(
        $token,
        $runId,
        $userAgent,
        $maxRetries,
        array $config = [],
        callable $delay = null
    ) {
        // Initialize handlers (start with those supplied in constructor)
        if (isset($config['handler']) && $config['handler'] instanceof HandlerStack) {
            $handlerStack = HandlerStack::create($config['handler']);
        } else {
            $handlerStack = HandlerStack::create();
        }
        // Set exponential backoff for cases where job detail returns error
        $handlerStack->push(Middleware::retry(
            self::createDefaultDecider($maxRetries),
            $delay
        ));
        // Set handler to set default headers
        $handlerStack->push(Middleware::mapRequest(
            function (RequestInterface $request) use ($token, $runId, $userAgent) {
                $req = $request->withHeader('User-Agent', $userAgent);
                if ($token) {
                    $req = $req->withHeader('X-StorageApi-Token', $token);
                }
                if (!$req->hasHeader('content-type')) {
                    $req = $req->withHeader('Content-type', 'application/json');
                }
                if ($runId) {
                    $req = $req->withHeader('X-KBC-RunId', $runId);
                }
                return $req;
            }
        ));

        // Set client logger
        if (isset($config['logger']) && $config['logger'] instanceof LoggerInterface) {
            $handlerStack->push(Middleware::log(
                $config['logger'],
                new MessageFormatter(
                    "{hostname} {req_header_User-Agent} - [{ts}] \"{method} {resource} {protocol}/{version}\" " .
                    "{code} {res_header_Content-Length}"
                )
            ));
        }

        // finally create the instance
        return new GuzzleClient(['base_url' => $this->url, 'handler' => $handlerStack]);
    }

    /**
     * Set parent component.
     * @param string $super Name of the parent component.
     */
    protected function setSuper($super)
    {
        $this->super = $super;
    }

    /**
     * Set request URL
     * @param string $url Base url for requests.
     */
    protected function setUrl($url)
    {
        $this->url = $url;
    }

    /**
     * @param $queueUrl
     */
    protected function setQueueUrl($queueUrl)
    {
        $this->queueUrl = $queueUrl;
    }

    /**
     * Decode a JSON response.
     * @param Response $response
     * @return array Parsed response.
     * @throws ClientException In case response cannot be read properly.
     */
    private function decodeResponse(Response $response)
    {
        $data = json_decode($response->getBody()->read($response->getBody()->getSize()), true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new ClientException('Unable to parse response body into JSON: ' . json_last_error());
        }

        return $data === null ? array() : $data;
    }

    /**
     * Create a new asynchronous job.
     *
     * @param string $component Component name
     * @param array $options Available options are:
     *      - config: configuration id.
     *      - configData: configuration data.
     *      - tag: image tag to run
     * @return array Response data with job status.
     * @throws ClientException
     */
    public function createJob($component, $options = array())
    {
        return $this->createAsyncJob($component .  "/run", "POST", $options);
    }

    /**
     * @param $path
     * @param string $method
     * @param array $options
     * @return array
     * @throws ClientException
     */
    public function createAsyncJob($path, $method = "POST", $options = array())
    {
        $uriParts = [];
        if ($this->super) {
            $uriParts[] = $this->super;
        }
        $uriParts[] = $path;
        if (substr($this->url, -1) == '/') {
            $uri = $this->url . implode('/', $uriParts);
        } else {
            $uri = $this->url . '/' . implode('/', $uriParts);
        }
        if (isset($options['tag'])) {
            $uri .= '/tag/' . $options['tag'];
        }
        $body = [];
        if (isset($options['body'])) {
            $body = $options['body'];
        }
        if (isset($options['config'])) {
            $body['config'] = $options['config'];
        }
        if (isset($options['configData'])) {
            $body['configData'] = $options['configData'];
        }

        try {
            $request = new Request($method, $uri, [], json_encode($body));
            $response = $this->guzzle->send($request);
        } catch (RequestException $e) {
            throw new ClientException($e->getMessage(), 0, $e);
        }
        return $this->decodeResponse($response);
    }

    /**
     * Get asynchronous job status (waiting, processing, etc.).
     *
     * @param int|string $job Job Id.
     * @return array Response data with job status.
     * @throws ClientException
     */
    public function getJob($job)
    {
        if (substr($this->queueUrl, -1) == '/') {
            $uri = $this->queueUrl . "queue/job/{$job}";
        } else {
            $uri = $this->queueUrl . "/queue/job/{$job}";
        }
        try {
            $request = new Request('GET', $uri);
            $response = $this->guzzle->send($request);
        } catch (RequestException $e) {
            throw new ClientException($e->getMessage(), 0, $e);
        }
        return $this->decodeResponse($response);
    }

    /**
     * Run a syrup job and wait for the result.
     *
     * @param string $component Component name.
     * @param array $options Available options are:
     *      - config: configuration id.
     *      - configData: configuration data.
     *      - tag: image tag to run
     * @return array Response data with job result.
     * @throws ClientException In case creation or waiting for the job failed.
     */
    public function runJob($component, array $options = [])
    {
        return $this->runAsyncAction($component . "/run", "POST", $options);
    }

    /**
     * Run  docker runner sync action
     *
     * @param string $syncActionBaseUrl
     * @param string $component
     * @param string $action
     * @param array $configData
     * @return array Sync action response
     * @throws ClientException In case of execution error
     */
    public function runSyncAction($syncActionBaseUrl, $component, $action, array $configData)
    {
        $uriParts = [];
        if ($this->super) {
            $uriParts[] = $this->super;
        }
        $uriParts[] = $component;
        $uriParts[] = 'action';
        $uriParts[] = $action;

        $uri = rtrim($syncActionBaseUrl, '/') . '/' . implode('/', $uriParts);

        $body = [
            'configData' => $configData,
        ];

        try {
            $request = new Request('POST', $uri, [], json_encode($body));
            $response = $this->guzzle->send($request);
        } catch (RequestException $e) {
            throw new ClientException($e->getMessage(), 0, $e);
        }
        return $this->decodeResponse($response);
    }

    /**
     * @param $path
     * @param string $method
     * @param array $options
     * @return array
     * @throws ClientException
     */
    public function runAsyncAction($path, $method = "POST", array $options = [])
    {
        $response = $this->createAsyncJob($path, $method, $options);
        if (!isset($response["id"])) {
            throw new ClientException("Invalid response.");
        }
        $finished = false;
        $attempt = 0;
        $job = array();
        while (!$finished) {
            $job = $this->getJob($response["id"]);
            if (in_array($job["status"], $this->jobFinishedStates)) {
                $finished = true;
            }
            $attempt++;
            sleep(min(pow(2, $attempt), $this->maxDelay));
        }
        return $job;
    }
}


<?php
namespace mnshankar\RoleBasedAuthority;

use Illuminate\Support\ServiceProvider;

class RoleBasedAuthorityServiceProvider extends ServiceProvider
{

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->package('mnshankar/role-based-authority');

        $this->app['authority'] = $this->app->share(function ($app)
        {
            $cache = $app['config']->get('role-based-authority::cache', false);
            $cache_ttl = $app['config']->get('role-based-authority::cache_ttl', 0);
            $cacheObj = $app->make('cache');
            if ($cache && $cacheObj->has('role-based-authority'))
            {
                return $cacheObj->get('role-based-authority');
            }
            $user = $app['auth']->user();
            $authority = new \Authority\Authority($user);
            $fn = $app['config']->get('role-based-authority::initialize', null);

            if ($fn) {
                $fn($authority);
            }
            if ($cache)
            {
                $cacheObj->put('role-based-authority', $authority, $cache_ttl);
            }
            return $authority;
        });
    }

    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return array(
            'authority'
        );
    }
}


<?php
/**
 * @package     Search
 * @author      Axel Etcheverry <axel@etcheverry.biz>
 * @copyright   Copyright (c) 2014 Axel Etcheverry (https://twitter.com/euskadi31)
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * @namespace
 */
namespace Search\Engine\Sphinx;

use Search\AbstractResponse;

class Response extends AbstractResponse
{
    /**
     * general success, command-specific reply follows
     */
    const OK         = 0;

    /**
     * general failure, error message follows
     */
    const ERROR      = 1;

    /**
     * temporary failure, error message follows, client should retry later
     */
    const RETRY      = 2;

    /**
     * general success, warning message and command-specific reply follow
     */
    const WARNING    = 3;

    /**
     *
     * @var string
     */
    protected $error;

    /**
     *
     * @var string
     */
    protected $warning;

    /**
     *
     * @var integer
     */
    protected $status = 0;

    /**
     *
     * @param array $results Sphinx results
     */
    public function __construct($results)
    {
        $this->status = (int)$results['status'];

        $this->error = $results['error'];
        $this->warning = $results['warning'];

        $this->total = $results['total'];

        if (isset($results['matches'])) {
            $this->container = $results['matches'];
        }
    }

    /**
     *
     * @return boolean
     */
    public function isError()
    {
        return ($this->status === self::ERROR || $this->status === self::RETRY);
    }

    /**
     *
     * @return boolean
     */
    public function isSuccessful()
    {
        return ($this->status === self::OK || $this->status === self::WARNING);
    }

    /**
     *
     * @return boolean
     */
    public function isWarning()
    {
        return ($this->status === self::WARNING);
    }

    /**
     * Get error message
     *
     * @return string
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * Get warning message
     *
     * @return string
     */
    public function getWarning()
    {
        return $this->warning;
    }

    /**
     * Get all messages
     *
     * @return string
     */
    public function getMessages()
    {
        $messages = array();

        if (!empty($this->error)) {
            $messages[] = $this->error;
        }

        if (!empty($this->warning)) {
            $messages[] = $this->warning;
        }

        return $messages;
    }
}


<?php

/*
 * This file is part of the slince/upload package.
 *
 * (c) Slince <taosikai@yeah.net>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Slince\Upload\Constraint;

use Slince\Upload\Exception\ConstraintException;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class MimeTypeConstraint implements ConstraintInterface
{
    /**
     * @var array
     */
    protected $allowedMimeTypes;

    public function __construct(array $allowedMimeTypes)
    {
        $this->allowedMimeTypes = $allowedMimeTypes;
    }

    /**
     * {@inheritdoc]
     */
    public function validate(UploadedFile $file)
    {
        foreach ($this->allowedMimeTypes as $mimeType) {
            if ($mimeType === $file->getClientMimeType()
                || (strpos($mimeType, '/*') !== false
                    && explode('/', $mimeType)[0] == explode('/', $file->getMimeType())[0])
            ) {
                return true;
            }
        }
        return false;
    }

    /**
     * {@inheritdoc}
     */
    public function getErrorMessage(UploadedFile $file)
    {
        return sprintf('File type "%s" is invalid', $file->getClientMimeType());
    }
}


<?php

namespace ParameterParser;

class FullUsageStyle
{
    /**
     * Retrieve which values from a Parameter
     * you would like displayed in the
     * full usage output.
     *
     * @return array
     */
    public static function all()
    {
        return self::allExcept([]);
    }

    /**
     * Retrieve which values from a Parameter
     * you would like displayed in the
     * full usage output.
     *
     * Any key in the $except array will be excluded.
     *
     * @param array $except
     *
     * @return array
     */
    public static function allExcept($except)
    {
        $result = [
            'parameter' => [
                // 9 = Length of the word 'Parameter'
                'longest' => 9 + $columnPadding,
                'values' => [],
                'fetch' => function ($parameter) {
                    return $parameter->prefix.$parameter->parameterName;
                },
            ],

            'properties' => [
                // 10 = Length of the word 'Properties'
                'longest' => 10 + $columnPadding,
                'values' => [],
                'fetch' => function ($parameter) {
                    return $parameter->getPropertiesAsString();
                },
            ],

            'aliases' => [
                // 7 = Length of the word 'Aliases'
                'longest' => 7 + $columnPadding,
                'values' => [],
                'fetch' => function ($parameter) {
                    return $parameter->getAliasUsage(false);
                },
            ],

            'description' => [
                // 11 = Length of the word 'Description'
                'longest' => 11 + $columnPadding,
                'values' => [],
                'fetch' => function ($parameter) {
                    return $parameter->description;
                },
            ],

            'required' => [
                // 8 = Length of the word 'Required'
                'longest' => 8 + $columnPadding,
                'values' => [],
                'fetch' => function ($parameter) {
                    return $parameter->required ? 'Yes' : '';
                },
            ],
        ];

        // Remove the exceptions
        foreach ($except as $exceptKey) {
            unset($result[$exceptKey]);
        }

        return $result;
    }
}