<?php
namespace wiggum\services\db;

class Grammar {

	protected $selectComponents = array (
			'aggregate',
			'columns',
			'from',
			'joins',
			'wheres',
			'groups',
			'orders',
            'limit',
            'offset'
	);

	/**
	 * Compile a select query into SQL.
	 *
	 * @param Builder $query
	 * @return string
	 */
	public function compileSelect(Builder $query) {
		if (is_null($query->columns)) $query->columns = array('*');

		return trim(implode(' ', $this->compileComponents($query)));
	}

	/**
	 * Compile the components necessary for a select clause.
	 *
	 * @param Builder $query
	 * @return array
	 */
	protected function compileComponents(Builder $query) {
		$sql = array();

		foreach ($this->selectComponents as $component) {
			if (!is_null($query->$component)) {
				$method = 'compile' . ucfirst($component);

				$sql[$component] = $this->$method($query, $query->$component);
			}
		}

		return $sql;
	}

	/**
	 *
	 * @param Builder $query
	 * @param array $aggregate
	 * @return string
	 */
	protected function compileAggregate(Builder $query, $aggregate) {

		$column = $this->columnize($aggregate['columns']);

		if ($query->distinct && $column !== '*') {
			$column = 'distinct '.$column;
		}

		return 'select '.$aggregate['function'].'('.$column.') as aggregate';
	}

	/**
	 * Compile the "select *" portion of the query.
	 *
	 * @param Builder $query
	 * @param array $columns
	 * @return string
	 */
	protected function compileColumns(Builder $query, $columns) {

		// If the query is performing an aggregating select, we will let that
		// compiler handle the building of the select clauses.
		if (!is_null($query->aggregate)) {
			return;
		}

		$select = $query->distinct ? 'select distinct ' : 'select ';

		return $select.$this->columnize($columns);
	}

	/**
	 * Compile the "from" portion of the query.
	 *
	 * @param Builder $query
	 * @param string $tables
	 * @return string
	 */
	protected function compileFrom(Builder $query, $tables) {
		return 'from ' . implode(', ', $this->wrapArray($tables));
	}

	/**
	 * Compile the "join" portions of the query.
	 *
	 * @param  \Illuminate\Database\Query\Builder  $query
	 * @param  array  $joins
	 * @return string
	 */
	protected function compileJoins(Builder $query, $joins) {
		$sql = array();

		$query->setBindings(array(), 'join');

		foreach ($joins as $join) {
			$table = $this->wrap($join->table);

			// First we need to build all of the "on" clauses for the join. There may be many
			// of these clauses so we will need to iterate through each one and build them
			// separately, then we'll join them up into a single string when we're done.
			$clauses = array();

			foreach ($join->clauses as $clause) {
				$clauses[] = $this->compileJoinConstraint($clause);
			}

			foreach ($join->bindings as $binding) {
				$query->addBinding($binding, 'join');
			}

			// Once we have constructed the clauses, we'll need to take the boolean connector
			// off of the first clause as it obviously will not be required on that clause
			// because it leads the rest of the clauses, thus not requiring any boolean.
			$clauses[0] = $this->removeLeadingBoolean($clauses[0]);

			$clauses = implode(' ', $clauses);

			$type = $join->type;

			// Once we have everything ready to go, we will just concatenate all the parts to
			// build the final join statement SQL for the query and we can then return the
			// final clause back to the callers as a single, stringified join statement.
			$sql[] = "$type join $table on $clauses";
		}

		return implode(' ', $sql);
	}

	/**
	 * Create a join clause constraint segment.
	 *
	 * @param  array   $clause
	 * @return string
	 */
	protected function compileJoinConstraint(array $clause) {
		$firstColumn = $this->wrap($clause['firstColumn']);

		if ($clause['where']) {
			if ($clause['operator'] === 'in' || $clause['operator'] === 'not in') {
				$secondColumn = '('.implode(', ', array_fill(0, $clause['secondColumn'], '?')).')';
			} else {
				$secondColumn = '?';
			}
		} else {
			$secondColumn = $this->wrap($clause['secondColumn']);
		}

		return "{$clause['boolean']} $firstColumn {$clause['operator']} $secondColumn";
	}

	/**
	 * Compile the "where" portions of the query.
	 *
	 * @param  Builder $query
	 * @return string
	 */
	protected function compileWheres(Builder $query) {
		$sql = array();

		if (is_null($query->wheres)) return '';

		// Each type of where clauses has its own compiler function which is responsible
		// for actually creating the where clauses SQL. This helps keep the code nice
		// and maintainable since each clause has a very small method that it uses.
		foreach ($query->wheres as $where) {
			$method = "where{$where['type']}";

			$sql[] = $where['boolean'].' '.$this->$method($query, $where);
		}

		// If we actually have some where clauses, we will strip off the first boolean
		// operator, which is added by the query builders for convenience so we can
		// avoid checking for the first clauses in each of the compilers methods.
		if (count($sql) > 0) {
			$sql = implode(' ', $sql);

			return 'where '.$this->removeLeadingBoolean($sql);
		}

		return '';
	}

	/**
	 *
	 * @param Builder $query
	 * @param array $where
	 * @return string
	 */
	protected function whereNested(Builder $query, $where) {
		$nested = $where['query'];

		return '('.substr($this->compileWheres($nested), 6).')';
	}

	/**
	 * Compile a basic where clause.
	 *
	 * @param Builder $query
	 * @param  array  $where
	 * @return string
	 */
	protected function whereBasic(Builder $query, $where) {
		return $this->wrap($where['column']).' '.$where['operator'].' ?';
	}

	/**
	 * Compile a "between" where clause.
	 *
	 * @param  Builder $query
	 * @param  array  $where
	 * @return string
	 */
	protected function whereBetween(Builder $query, $where) {
		$between = $where['not'] ? 'not between' : 'between';

		return $this->wrap($where['column']).' '.$between.' ? and ?';
	}

	/**
	 * Compile a "where in" clause.
	 *
	 * @param  Builder $query
	 * @param  array  $where
	 * @return string
	 */
	protected function whereIn(Builder $query, $where) {
		$in = $where['not'] ? 'not in' : 'in';

		if (empty($where['values'])) return '0 = 1';

		$values = $this->parameterize($where['values']);

		return $this->wrap($where['column']).' '.$in.' ('.$values.')';
	}

	/**
	 * Compile a "where null" clause.
	 *
	 * @param  Builder $query
	 * @param  array  $where
	 * @return string
	 */
	protected function whereNull(Builder $query, $where) {
		$null = $where['not'] ? 'not null' : 'null';

		return $this->wrap($where['column']).' is '.$null;
	}

	/**
	 * Compile the "group by" portions of the query.
	 *
	 * @param  Builder $query
	 * @param  array  $groups
	 * @return string
	 */
	protected function compileGroups(Builder $query, $groups) {
		return 'group by '.$this->columnize($groups);
	}

	/**
	 * Compile the "order by" portions of the query.
	 *
	 * @param  Builder $query
	 * @param  array  $orders
	 * @return string
	 */
	protected function compileOrders(Builder $query, $orders) {
		return 'order by '.implode(', ', array_map(function($order) {
			return $this->wrap($order['column']).' '.$order['direction'];
		}, $orders));
	}

	/**
	 * Compile the "limit" portions of the query.
	 *
	 * @param  Builder $query
	 * @param  int  $limit
	 * @return string
	 */
	protected function compileLimit(Builder $query, $limit) {
		return 'limit '.(int) $limit;
	}

	/**
	 * Compile the "offset" portions of the query.
	 *
	 * @param  Builder $query
	 * @param  int  $offset
	 * @return string
	 */
	protected function compileOffset(Builder $query, $offset) {
		return 'offset '.(int) $offset;
	}

	/**
	 *
	 * @param Builder $query
	 * @param unknown $value
	 * @return string
	 */
	protected function compileLock(Builder $query, $value) {
		if (is_string($value)) {
			return $value;
		}
		return $value ? 'for update' : 'lock in share mode';
	}

	/**
	 * Compile an insert statement into SQL.
	 *
	 * @param  Builder $query
	 * @param  array  $values
	 * @return string
	 */
	public function compileInsert(Builder $query) {
		$table = $this->wrap($query->from[0]);

		$columns = $this->columnize(array_keys(reset($query->inserts)));

		// We need to build a list of parameter place-holders of values that are bound
		// to the query. Each insert should have the exact same amount of parameter
		// bindings so we can just go off the first list of values in this array.
		$parameters = $this->parameterize(reset($query->inserts));

		$value = array_fill(0, count($query->inserts), "($parameters)");

		$parameters = implode(', ', $value);

		return "insert into $table ($columns) values $parameters";
	}

	/**
	 * Compile an update statement into SQL.
	 *
	 * @param  Builder $query
	 * @param  array  $values
	 * @return string
	 */
	public function compileUpdate(Builder $query) {
		$table = $this->wrap($query->from[0]);

		// Each one of the columns in the update statements needs to be wrapped in the
		// keyword identifiers, also a place-holder needs to be created for each of
		// the values in the list of bindings so we can make the sets statements.
		$columns = array();

		foreach ($query->updates as $key => $value) {
			$columns[] = $this->wrap($key).' = ?';
		}

		$columns = implode(', ', $columns);

		$joins = isset($query->joins) ? ' '.$this->compileJoins($query, $query->joins) : '';

		// Of course, update queries may also be constrained by where clauses so we'll
		// need to compile the where clauses and attach it to the query so only the
		// intended records are updated by the SQL statements we generate to run.
		$where = $this->compileWheres($query);

		$sql = trim("update {$table}{$joins} set {$columns} {$where}");

		if (isset($query->orders)) {
			$sql .= ' '.$this->compileOrders($query, $query->orders);
		}
		if (isset($query->limit)) {
			$sql .= ' '.$this->compileLimit($query, $query->limit);
		}

		return trim($sql);
	}

	/**
	 * Compile a delete statement into SQL.
	 *
	 * @param  Builder $query
	 * @return string
	 */
	public function compileDelete(Builder $query) {
		$table = $this->wrap($query->from[0]);

		$where = $this->compileWheres($query);

		if (isset($query->joins)) {
			$joins = ' '.$this->compileJoins($query, $query->joins);

			$sql = trim("delete $table from {$table}{$joins} $where");

		} else {
			$sql = trim("delete from $table $where");

			if (isset($query->orders)) {
				$sql .= ' '.$this->compileOrders($query, $query->orders);
			}

			if (isset($query->limit)) {
				$sql .= ' '.$this->compileLimit($query, $query->limit);
			}
		}
		return $sql;

	}

	/**
	 * Compile the query to determine the list of columns.
	 *
	 * @return string
	 */
	public function compileColumnExists() {
		return 'select column_name from information_schema.columns where table_name = ?';
	}

	// Helper methods

	/**
	 * Wrap a value in keyword identifiers.
	 *
	 * @param  string  $value
	 * @return string
	 */
	private function wrap($value) {

		if (strpos(strtolower($value), 'null') !== false) {
			return $value;
		}

		// If the value being wrapped has a column alias we will need to separate out
		// the pieces so we can wrap each of the segments of the expression on it
		// own, and then joins them both back together with the "as" connector.
		if (strpos(strtolower($value), ' as ') !== false) {
			$segments = explode(' ', $value);

			return $this->wrap($segments[0]).' as '.$this->wrapValue($segments[2]);
		}

		$wrapped = array();

		$segments = explode('.', $value);

		// If the value is not an aliased table expression, we'll just wrap it like
		// normal, so if there is more than one segment, we will wrap the first
		// segments as if it was a table and the rest as just regular values.
		foreach ($segments as $key => $segment) {
			$wrapped[] = $this->wrapValue($segment);
		}

		return implode('.', $wrapped);
	}

	private function wrapValue($value) {
		if ($value === '*') return $value;

		return '`'.str_replace('`', '', $value).'`';
	}

	/**
	 * Create query parameter place-holders for an array.
	 *
	 * @param  array $values
	 * @return string
	 */
	private function parameterize(array $values) {
		return implode(', ', array_fill(0 , count($values), '?'));
	}

	/**
	 * Convert an array of column names into a delimited string.
	 *
	 * @param  array $columns
	 * @return string
	 */
	private function columnize(array $columns) {
		return implode(', ', array_map(array($this, 'wrap'), $columns));
	}

	/**
	 * Wrap an array of values.
	 *
	 * @param  array  $values
	 * @return array
	 */
	private function wrapArray(array $values) {
		return array_map(array($this, 'wrap'), $values);
	}

	/**
	 * Remove the leading boolean from a statement.
	 *
	 * @param string $value
	 * @return string
	 */
	private function removeLeadingBoolean($value) {
		return preg_replace('/and |or /', '', $value, 1);
	}
}


<?php

namespace Steem;

class Operations
{

    /**
     * Vote
     *
     * @param string $voter     Voting user
     * @param string $author    Up-voted user
     * @param string $permalink Permalink of the post
     * @param int    $weight    Voting weight
     * @return array
     */
    public function vote(string $voter, string $author, string $permalink, int $weight)
    {
        $request = [
            'operations' =>
                [
                    [
                        'vote',
                        [
                            'voter'    => $voter,
                            'author'   => $author,
                            'permlink' => $permalink,
                            'weight'   => (int) $weight,
                        ]
                    ]
                ]
        ];

        return $request;
    }

    /**
     * New post
     *
     * @param string $author The author who is posting
     * @param string $title  Post title, the permalink is gonna be created by title
     * @param string $body   Body of the post
     * @param array  $tags   Array of tags
     * @param string $app    Name of the application in use for the post
     * @return array
     */
    public function post(string $author, string $title, string $body, array $tags, string $app = '')
    {
        $first_tag = Helpers::slug(array_shift($tags));
        $shorty    = Helpers::limit($title, 35);
        $permalink = Helpers::slug($shorty).'-'.time();
        $metadata  = [];

        if (count($tags) > 0)
        {
            $metadata['tags'] = $tags;
        }
        if (!empty($app))
        {
            $metadata['app'] = $app;
        }

        $metadata  = json_encode($metadata);
        $request   = [
            'operations' =>
                [
                    [
                        'comment',
                        [
                            'parent_author'   => '',
                            'parent_permlink' => $first_tag,
                            'author'          => $author,
                            'permlink'        => $permalink,
                            'title'           => $title,
                            'body'            => $body,
                            'json_metadata'   => empty($metadata) ? '' : $metadata
                        ]
                    ]
                ]
        ];

        return $request;
    }

    /**
     * New comment
     *
     * @param string $parent_author   Original poster or "parent author"
     * @param string $parent_permlink Original post permalink or "parent permalink"
     * @param string $author          The author who is posting
     * @param string $permlink        Permalink for the comment
     * @param string $body            Body of the post
     * @param string $app             Name of the application in use for the post
     * @return array
     */
    public function comment(string $parent_author, string $parent_permlink, string $author, string $permlink, string $body, string $app = '')
    {
        $permlink  = Helpers::limit($permlink, 35);
        $permalink = Helpers::slug($permlink).'-'.time();
        $metadata  = [];

        if (!empty($app))
        {
            $metadata['app'] = $app;
        }

        $metadata  = json_encode($metadata);
        $request   = [
            'operations' =>
                [
                    [
                        'comment',
                        [
                            'parent_author'   => $parent_author,
                            'parent_permlink' => $parent_permlink,
                            'author'          => $author,
                            'permlink'        => $permalink,
                            'title'           => '',
                            'body'            => $body,
                            'json_metadata'   => empty($metadata) ? '' : $metadata
                        ]
                    ]
                ]
        ];

        return $request;
    }

    /**
     * Comment Options
     *
     * @param string $author                 Author
     * @param string $permalink              Permalink of the post
     * @param string $max_accepted_payout    Max accepted payout
     * @param int    $percent_steem_dollars  Percent SBD
     * @param bool   $allow_votes            Allow votes
     * @param bool   $allow_curation_rewards Allow curation rewards
     * @param array  $extensions             Extensions
     * @return array
     */
    public function comment_options(string $author, string $permalink, string $max_accepted_payout, int $percent_steem_dollars, bool $allow_votes, bool $allow_curation_rewards, array $extensions = [])
    {
        $request = [
            'operations' =>
                [
                    [
                        'comment_options',
                        [
                            'author'                 => $author,
                            'permlink'               => $permalink,
                            'max_accepted_payout'    => $max_accepted_payout,
                            'percent_steem_dollars'  => $percent_steem_dollars,
                            'allow_votes'            => $allow_votes,
                            'allow_curation_rewards' => $allow_curation_rewards,
                            'extensions'             => $extensions
                        ]
                    ]
                ]
        ];

        return $request;
    }
}


<?php

namespace Kcs\FunctionMock;

use Kcs\FunctionMock\Exception\InvalidArgumentException;
use Kcs\FunctionMock\Registry\MockRegistry;
use Prophecy\Argument;
use Prophecy\Prophet;

class FunctionProphecy
{
    /**
     * @var string
     */
    private $name;

    /**
     * @var NamespaceProphecy
     */
    private $namespaceProphecy;

    /**
     * @var Promise\PromiseInterface
     */
    private $promise;

    /**
     * @var array
     */
    private $checkedPredictions = [];

    /**
     * @var Argument\ArgumentsWildcard
     */
    private $argumentsWildcard;

    /**
     * @var Prediction\PredictionInterface
     */
    private $prediction;

    public function __construct(NamespaceProphecy $namespaceProphecy, $functionName, $arguments = null)
    {
        $this->name = $functionName;
        $this->namespaceProphecy = $namespaceProphecy;

        if (! function_exists($functionName)) {
            throw new \Exception();
        }

        $reflectedFunction = new \ReflectionFunction($functionName);
        if (null !== $arguments) {
            $this->withArguments($arguments);
        }

        if (version_compare(PHP_VERSION, '7.0', '>=') && true === $reflectedFunction->hasReturnType()) {
            $type = (string) $reflectedFunction->getReturnType();
            $this->will(function () use ($type) {
                switch ($type) {
                    case 'string': return '';
                    case 'float':  return 0.0;
                    case 'int':    return 0;
                    case 'bool':   return false;
                    case 'array':  return [];

                    case 'callable':
                    case 'Closure':
                        return function () {
                        };

                    case 'Traversable':
                    case 'Generator':
                        $generator = function () {
                            yield;
                        };

                        return $generator();

                    default:
                        $prophet = new Prophet();

                        return $prophet->prophesize($type)->reveal();
                }
            });
        }
    }

    /**
     * Sets argument wildcard.
     *
     * @param array|Argument\ArgumentsWildcard $arguments
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     */
    public function withArguments($arguments)
    {
        if (is_array($arguments)) {
            $arguments = new Argument\ArgumentsWildcard($arguments);
        }

        if (!$arguments instanceof Argument\ArgumentsWildcard) {
            throw new InvalidArgumentException(sprintf(
                "Either an array or an instance of ArgumentsWildcard expected as\n".
                'a `FunctionProphecy::withArguments()` argument, but got %s.',
                gettype($arguments)
            ));
        }

        $this->argumentsWildcard = $arguments;

        return $this;
    }

    /**
     * Sets custom promise to the prophecy.
     *
     * @param callable|Promise\PromiseInterface $promise
     *
     * @return $this
     *
     * @throws \Prophecy\Exception\InvalidArgumentException
     */
    public function will($promise)
    {
        if (is_callable($promise)) {
            $promise = new Promise\CallbackPromise($promise);
        }

        if (!$promise instanceof Promise\PromiseInterface) {
            throw new InvalidArgumentException(sprintf(
                'Expected callable or instance of PromiseInterface, but got %s.',
                gettype($promise)
            ));
        }

        $this->bind();
        $this->promise = $promise;

        return $this;
    }

    /**
     * Sets return promise to the prophecy.
     *
     * @see Promise\ReturnPromise
     *
     * @return $this
     */
    public function willReturn()
    {
        return $this->will(new Promise\ReturnPromise(func_get_args()));
    }

    /**
     * Sets return argument promise to the prophecy.
     *
     * @param int $index The zero-indexed number of the argument to return
     *
     * @see Promise\ReturnArgumentPromise
     *
     * @return $this
     */
    public function willReturnArgument($index = 0)
    {
        return $this->will(new Promise\ReturnArgumentPromise($index));
    }

    /**
     * Sets throw promise to the prophecy.
     *
     * @see Promise\ThrowPromise
     *
     * @param string|\Exception $exception Exception class or instance
     *
     * @return $this
     */
    public function willThrow($exception)
    {
        return $this->will(new Promise\ThrowPromise($exception));
    }

    /**
     * Sets custom prediction to the prophecy.
     *
     * @param callable|Prediction\PredictionInterface $prediction
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     */
    public function should($prediction)
    {
        if (is_callable($prediction)) {
            $prediction = new Prediction\CallbackPrediction($prediction);
        }

        if (!$prediction instanceof Prediction\PredictionInterface) {
            throw new InvalidArgumentException(sprintf(
                'Expected callable or instance of PredictionInterface, but got %s.',
                gettype($prediction)
            ));
        }

        $this->bind();
        $this->prediction = $prediction;

        return $this;
    }

    /**
     * Sets call prediction to the prophecy.
     *
     * @see Prediction\CallPrediction
     *
     * @return $this
     */
    public function shouldBeCalled()
    {
        return $this->should(new Prediction\CallPrediction());
    }

    /**
     * Sets no calls prediction to the prophecy.
     *
     * @see Prediction\NoCallsPrediction
     *
     * @return $this
     */
    public function shouldNotBeCalled()
    {
        return $this->should(new Prediction\NoCallsPrediction());
    }

    /**
     * Sets call times prediction to the prophecy.
     *
     * @see Prediction\CallTimesPrediction
     *
     * @param $count
     *
     * @return $this
     */
    public function shouldBeCalledTimes($count)
    {
        return $this->should(new Prediction\CallTimesPrediction($count));
    }

    /**
     * Checks provided prediction immediately.
     *
     * @param callable|Prediction\PredictionInterface $prediction
     *
     * @return $this
     *
     * @throws InvalidArgumentException
     * @throws \Exception
     */
    public function shouldHave($prediction)
    {
        if (is_callable($prediction)) {
            $prediction = new Prediction\CallbackPrediction($prediction);
        }

        if (!$prediction instanceof Prediction\PredictionInterface) {
            throw new InvalidArgumentException(sprintf(
                'Expected callable or instance of PredictionInterface, but got %s.',
                gettype($prediction)
            ));
        }

        if (null === $this->promise) {
            $this->willReturn();
        }

        $calls = $this->namespaceProphecy->findCalls($this->name, $this->getArgumentsWildcard());

        try {
            $prediction->check($calls, $this);
            $this->checkedPredictions[] = $prediction;
        } catch (\Exception $e) {
            $this->checkedPredictions[] = $prediction;

            throw $e;
        }

        return $this;
    }

    /**
     * Checks call prediction.
     *
     * @see Prediction\CallPrediction
     *
     * @return $this
     */
    public function shouldHaveBeenCalled()
    {
        return $this->shouldHave(new Prediction\CallPrediction());
    }

    /**
     * Checks no calls prediction.
     *
     * @see Prediction\NoCallsPrediction
     *
     * @return $this
     */
    public function shouldNotHaveBeenCalled()
    {
        return $this->shouldHave(new Prediction\NoCallsPrediction());
    }

    /**
     * Checks call times prediction.
     *
     * @see Prediction\CallTimesPrediction
     *
     * @param int $count
     *
     * @return $this
     */
    public function shouldHaveBeenCalledTimes($count)
    {
        return $this->shouldHave(new Prediction\CallTimesPrediction($count));
    }

    /**
     * Checks currently registered [with should(...)] prediction.
     */
    public function checkPrediction()
    {
        if (null === $this->prediction) {
            return;
        }

        $this->shouldHave($this->prediction);
    }

    /**
     * Returns currently registered promise.
     *
     * @return null|Promise\PromiseInterface
     */
    public function getPromise()
    {
        return $this->promise;
    }

    /**
     * Returns currently registered prediction.
     *
     * @return null|Prediction\PredictionInterface
     */
    public function getPrediction()
    {
        return $this->prediction;
    }

    /**
     * Returns predictions that were checked on this object.
     *
     * @return Prediction\PredictionInterface[]
     */
    public function getCheckedPredictions()
    {
        return $this->checkedPredictions;
    }

    /**
     * Returns arguments wildcard.
     *
     * @return Argument\ArgumentsWildcard
     */
    public function getArgumentsWildcard()
    {
        return $this->argumentsWildcard;
    }

    private function bind()
    {
        $this->getNamespace()->addProphecy($this);

        $registry = MockRegistry::getInstance();
        if ($registry->has($this->getFQName())) {
            return;
        }

        $registry->register($this);
    }

    public function getName()
    {
        return $this->name;
    }

    public function getNamespace()
    {
        return $this->namespaceProphecy;
    }

    public function getFQName()
    {
        return $this->namespaceProphecy->getName().'\\'.$this->name;
    }
}


<?php

namespace Yami\SheetFight\Model;

use InvalidArgumentException;
use LogicException;
use RangeException;
use ArrayAccess;
use Traversable;

/**
 * Represents an action done by the character in the game.
 *
 * @author Kevin GITTENS <kgittens973@gmail.com>
 * @author Ludovic FLEURY <ludo.fleury@gmail.com>
 */
class Move implements MoveInterface
{
    /**
     * @var string normal|special|super
     */
    private $type;

    /**
     * @var string
     */
    private $name;

    /**
     * @var string crouching|standing|airborne
     */
    private $initialPosition;

    /**
     * @var \Yami\SheetFight\Model\InputInterface
     */
    private $inputs;

    /**
     * @var int Positive integer
     */
    private $damage;

    /**
     * @var int integer
     */
    private $meterGain;

    /**
     * @var string low|mid|high
     */
    private $hitLevel;

    /**
     * @var \Yami\SheetFight\Model\MoveInterface[]
     */
    private $cancelAbilities;

    /**
     * @var \Yami\SheetFight\Model\FrameDataInterface
     */
    private $frameData;

    public function __construct(
        $type,
        $name,
        $initialPosition,
        $inputs,
        $damage,
        $meterGain,
        $hitLevel,
        $cancelAbilities,
        FrameDataInterface $frameData
    ) {
        if (!is_string($name)) {
            throw new InvalidArgumentException('The name should be a string');
        }

        switch (false) {
            case is_string($initialPosition):
                throw new InvalidArgumentException('The initial position should be a string');
            case in_array($initialPosition, ['standing', 'crouching', 'airborne']):
                throw new InvalidArgumentException('Invalid initial position');
        }

        if (!is_array($inputs)) {
            throw new InvalidArgumentException('The inputs should be an array');
        }

        if (0 === count($inputs)) {
            throw new InvalidArgumentException('The inputs should not be empty');
        }

        foreach ($inputs as $input) {
            if (!($input instanceof InputInterface)) {
                throw new InvalidArgumentException('The inputs should contain only input');
            }
        }

        if (!is_int($damage)) {
            throw new InvalidArgumentException('The damage should be an integer');
        }

        if ($damage < 0) {
            throw new RangeException('The damage should not be negative');
        }

        if (!is_int($meterGain)) {
            throw new InvalidArgumentException('The meter gain should be an integer');
        }

        switch (false) {
            case is_string($hitLevel):
                throw new InvalidArgumentException('The hit level should be string');
            case in_array($hitLevel, ['low', 'mid', 'high']):
                throw new InvalidArgumentException('Invalid hit level');
        }

        if (!(is_array($cancelAbilities) || ($cancelAbilities instanceof Traversable && $cancelAbilities instanceof ArrayAccess))) {
            throw new InvalidArgumentException('The cancel abilities should be an array');
        }

        $uniqueCancelAbilities = [];
        foreach ($cancelAbilities as $index => $cancelAbility) {
            if (!($cancelAbility instanceof MoveInterface)) {
                throw new InvalidArgumentException('The cancel abilities should contain only moves');
            }

            $serializedInputs = $cancelAbility->getInputs(true);

            if (isset($uniqueCancelAbilities[$serializedInputs])) {
                throw new LogicException('The cancel abilities should contain unique moves');
            }

            $uniqueCancelAbilities[$serializedInputs] = true;
        }
        unset($uniqueCancelAbilities);

        $this->type = $type;
        $this->name = $name;
        $this->initialPosition = $initialPosition;
        $this->inputs = $inputs;
        $this->damage = $damage;
        $this->meterGain = $meterGain;
        $this->hitLevel = $hitLevel;
        $this->cancelAbilities = $cancelAbilities;
        $this->frameData = $frameData;
    }

    /**
     * {@inheritdoc}
     *
     * @return bool
     */
    public function isNormal()
    {
        return MoveInterface::TYPE_NORMAL === $this->type;
    }

    /**
     * {@inheritdoc}
     *
     * @return bool
     */
    public function isSpecial()
    {
        return MoveInterface::TYPE_SPECIAL === $this->type;
    }

    /**
     * {@inheritdoc}
     *
     * @return bool
     */
    public function isSuper()
    {
        return MoveInterface::TYPE_SUPER === $this->type;
    }

    /**
     * {@inheritdoc}
     *
     * @return string
     */
    public function getType()
    {
        return $this->type;
    }

    /**
     * {@inheritdoc}
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     *
     * @return string standing, crouching or jumping
     */
    public function getInitialPosition()
    {
        return $this->initialPosition;
    }

    /**
     * {@inheritdoc}
     *
     * @return Yami\SheetFight\Model\InputInterface[]|string
     */
    public function getInputs($asString = false)
    {
        if ($asString) {
            $inputs = '';
            foreach ($this->inputs as $input) {
                $inputs .= $input->getValue();
            }
        } else {
            $inputs = $this->inputs;
        }

        return $inputs;
    }

    /**
     * {@inheritdoc}
     *
     * @return int
     */
    public function getDamage()
    {
        return $this->damage;
    }

    /**
     * {@inheritdoc}
     *
     * @return int
     */
    public function getMeterGain()
    {
        return $this->meterGain;
    }

    /**
     * {@inheritdoc}
     *
     * @return string low, mid or high
     */
    public function getHitLevel()
    {
        return $this->hitLevel;
    }

    /**
     * {@inheritdoc}
     *
     * @return Yami\SheetFight\Model\MoveInterface[]
     */
    public function getCancelAbilities()
    {
        return $this->cancelAbilities;
    }

    /**
     * {@inheritdoc}
     *
     * @return Yami\SheetFight\Model\FrameDataInterface
     */
    public function getFrameData()
    {
        return $this->frameData;
    }

    /**
     * {@inheritdoc}
     *
     * @param MoveInterface $otherMove
     *
     * @return bool
     */
    public function equals(MoveInterface $otherMove)
    {
        return $this->getInputs(true) === $otherMove->getInputs(true);
    }
}


<?php namespace RestGalleries;

use Illuminate\Support\Collection;
use RestGalleries\Http\Guzzle\Plugins\GuzzleAuth;
use RestGalleries\Http\Guzzle\Plugins\GuzzleCache;
use RestGalleries\Interfaces\GalleryAdapter;

/**
 * Abstract model CRUD-type to simplify the interaction with api services.
 */
abstract class RestGallery
{
    /**
     * Api service name.
     *
     * @var string
     */
    protected $service;

    /**
     * Credentials to connect with an api service,
     *
     * @var array
     */
    protected $clientCredentials = [];

    /**
     * It will store the http plugins.
     *
     * @var array
     */
    protected $plugins = [];

    /**
     * Returns all galleries (and its photos) from an api service.
     *
     * @return \Illuminate\Support\Collection|null
     */
    public function all()
    {
        $models = $this->newGallery()->all();

        if (! empty($models)) {
            return $this->newCollection($models);
        }

    }

    /**
     * Returns an ArrayObject type with the given models.
     *
     * @param  array $models
     * @return \Illuminate\Support\Collection
     */
    public function newCollection(array $models =array())
    {
        return new Collection($models);
    }

    /**
     * Finds and returns a specific gallery from an api service.
     *
     * @param  string  $id
     * @return \Illuminate\Support\Fluent|null
     */
    public function find($id)
    {
        return $this->newGallery()->find($id);
    }

    /**
     * This method create a new service gallery object to interact with the external api service.
     *
     * @return RestGalleries\APIs\<service>\Gallery
     */
    public function newGallery(GalleryAdapter $gallery = null)
    {
        if (empty($gallery)) {
            $class   = $this->getNamespaceService() . 'Gallery';
            $gallery = new $class;
        }

        if (! empty($this->plugins)) {
            array_walk($this->plugins, [$gallery, 'addPlugin']);
        }

        return $gallery;

    }

    private function getNamespaceService()
    {
        $service = get_class_namespace($this);
        $service .= '\\APIs\\';
        $service .= $this->getService();
        $service .= '\\';

        return $service;
    }

    /**
     * Sets the current service api name to interact with it.
     *
     * @param  string  $service
     * @return void
     */
    public function setService($service)
    {
        $this->service = $service;
        return $this;
    }

    /**
     * If service name is configured, return it, but returns the child class name for the service api name.
     *
     * @return string
     */
    public function getService()
    {
        if (isset($this->service)) {
            return $this->service;
        }

        return class_basename($this);

    }

    /**
     * Makes the authentication for the requests,
     *
     * @param  array  $tokenCredentials
     * @return object
     */
    public function setAuth(array $tokenCredentials)
    {
        $this->plugins['auth'] = new GuzzleAuth($tokenCredentials);
        return $this;
    }

    /**
     * Creates the cache plugin.
     *
     * @param string $system
     * @param array  $path
     */
    public function setCache($system, array $path = array())
    {
        $this->plugins['cache'] = new GuzzleCache($system, $path);
        return $this;
    }

    /**
     * Returns the plugin arrau that contains the Http plugins.
     *
     * @return array
     */
    public function getPlugins()
    {
        return $this->plugins;
    }

    /**
     * Takes account credentials and calls the user object to make the requests to get the api authorization.
     *
     * @param  string $callback
     * @return \Illuminate\Support\Fluent
     */
    public static function connect($callback = '')
    {
        $instance = new static;
        $user     = $instance->newUser();

        if (! empty($callback)) {
            $instance->clientCredentials['callback'] = $callback;
        }

        return $user->connect($instance->clientCredentials);

    }

    /**
     * Investigates if the access tokens still are valid. calling the user object and making the respective requests,
     *
     * @param  array  $tokenCredentials
     * @return \Illuminate\Support\Fluent
     */
    public static function verifyCredentials(array $tokenCredentials)
    {
        $instance = new static;
        $user     = $instance->newUser();

        return $user->verifyCredentials($tokenCredentials);

    }

    /**
     * Creates new user object that will interact with the api service.
     *
     * @return RestGalleries\APIs\<service>\User
     */
    public function newUser()
    {
        $class = $this->getNamespaceService() . 'User';
        return new $class;
    }

}


<?php

namespace Think\Crypt\Driver;

/**
 * Des 加密实现类
 * Converted from JavaScript to PHP by Jim Gibbs, June 2004 Paul Tero, July 2001
 * Optimised for performance with large blocks by Michael Hayworth, November 2001
 * http://www.netdealing.com
 */

class Des
{

    /**
     * 加密字符串
     * @param string $str 字符串
     * @param string $key 加密key
     * @param integer $expire 有效期（秒）
     * @return string
     */
    public static function encrypt($str, $key, $expire = 0)
    {
        if ("" == $str) {
            return "";
        }
        $expire = sprintf('%010d', $expire ? $expire + time() : 0);
        $str = $expire.$str;

        return self::_des($key, $str, 1);
    }

    /**
     * 解密字符串
     * @param string $str 字符串
     * @param string $key 加密key
     * @return string
     */
    public static function decrypt($str, $key)
    {
        if ("" == $str) {
            return "";
        }
        $data = self::_des($key, $str, 0);
        $expire = substr($data, 0, 10);
        if ($expire > 0 && $expire < time()) {
            return '';
        }
        $data = substr($data, 10);

        return $data;
    }

    /**
     * Des算法
     * @param string $key 加密key
     * @param $message
     * @param $encrypt
     * @param int $mode
     * @param null $iv
     * @return string
     */
    private static function _des($key, $message, $encrypt, $mode = 0, $iv = null)
    {
        //declaring this locally speeds things up a bit
        $spfunction1 = [
            0x1010400,
            0,
            0x10000,
            0x1010404,
            0x1010004,
            0x10404,
            0x4,
            0x10000,
            0x400,
            0x1010400,
            0x1010404,
            0x400,
            0x1000404,
            0x1010004,
            0x1000000,
            0x4,
            0x404,
            0x1000400,
            0x1000400,
            0x10400,
            0x10400,
            0x1010000,
            0x1010000,
            0x1000404,
            0x10004,
            0x1000004,
            0x1000004,
            0x10004,
            0,
            0x404,
            0x10404,
            0x1000000,
            0x10000,
            0x1010404,
            0x4,
            0x1010000,
            0x1010400,
            0x1000000,
            0x1000000,
            0x400,
            0x1010004,
            0x10000,
            0x10400,
            0x1000004,
            0x400,
            0x4,
            0x1000404,
            0x10404,
            0x1010404,
            0x10004,
            0x1010000,
            0x1000404,
            0x1000004,
            0x404,
            0x10404,
            0x1010400,
            0x404,
            0x1000400,
            0x1000400,
            0,
            0x10004,
            0x10400,
            0,
            0x1010004,
        ];
        $spfunction2 = [
            -0x7fef7fe0,
            -0x7fff8000,
            0x8000,
            0x108020,
            0x100000,
            0x20,
            -0x7fefffe0,
            -0x7fff7fe0,
            -0x7fffffe0,
            -0x7fef7fe0,
            -0x7fef8000,
            -0x80000000,
            -0x7fff8000,
            0x100000,
            0x20,
            -0x7fefffe0,
            0x108000,
            0x100020,
            -0x7fff7fe0,
            0,
            -0x80000000,
            0x8000,
            0x108020,
            -0x7ff00000,
            0x100020,
            -0x7fffffe0,
            0,
            0x108000,
            0x8020,
            -0x7fef8000,
            -0x7ff00000,
            0x8020,
            0,
            0x108020,
            -0x7fefffe0,
            0x100000,
            -0x7fff7fe0,
            -0x7ff00000,
            -0x7fef8000,
            0x8000,
            -0x7ff00000,
            -0x7fff8000,
            0x20,
            -0x7fef7fe0,
            0x108020,
            0x20,
            0x8000,
            -0x80000000,
            0x8020,
            -0x7fef8000,
            0x100000,
            -0x7fffffe0,
            0x100020,
            -0x7fff7fe0,
            -0x7fffffe0,
            0x100020,
            0x108000,
            0,
            -0x7fff8000,
            0x8020,
            -0x80000000,
            -0x7fefffe0,
            -0x7fef7fe0,
            0x108000,
        ];
        $spfunction3 = [
            0x208,
            0x8020200,
            0,
            0x8020008,
            0x8000200,
            0,
            0x20208,
            0x8000200,
            0x20008,
            0x8000008,
            0x8000008,
            0x20000,
            0x8020208,
            0x20008,
            0x8020000,
            0x208,
            0x8000000,
            0x8,
            0x8020200,
            0x200,
            0x20200,
            0x8020000,
            0x8020008,
            0x20208,
            0x8000208,
            0x20200,
            0x20000,
            0x8000208,
            0x8,
            0x8020208,
            0x200,
            0x8000000,
            0x8020200,
            0x8000000,
            0x20008,
            0x208,
            0x20000,
            0x8020200,
            0x8000200,
            0,
            0x200,
            0x20008,
            0x8020208,
            0x8000200,
            0x8000008,
            0x200,
            0,
            0x8020008,
            0x8000208,
            0x20000,
            0x8000000,
            0x8020208,
            0x8,
            0x20208,
            0x20200,
            0x8000008,
            0x8020000,
            0x8000208,
            0x208,
            0x8020000,
            0x20208,
            0x8,
            0x8020008,
            0x20200,
        ];
        $spfunction4 = [
            0x802001,
            0x2081,
            0x2081,
            0x80,
            0x802080,
            0x800081,
            0x800001,
            0x2001,
            0,
            0x802000,
            0x802000,
            0x802081,
            0x81,
            0,
            0x800080,
            0x800001,
            0x1,
            0x2000,
            0x800000,
            0x802001,
            0x80,
            0x800000,
            0x2001,
            0x2080,
            0x800081,
            0x1,
            0x2080,
            0x800080,
            0x2000,
            0x802080,
            0x802081,
            0x81,
            0x800080,
            0x800001,
            0x802000,
            0x802081,
            0x81,
            0,
            0,
            0x802000,
            0x2080,
            0x800080,
            0x800081,
            0x1,
            0x802001,
            0x2081,
            0x2081,
            0x80,
            0x802081,
            0x81,
            0x1,
            0x2000,
            0x800001,
            0x2001,
            0x802080,
            0x800081,
            0x2001,
            0x2080,
            0x800000,
            0x802001,
            0x80,
            0x800000,
            0x2000,
            0x802080,
        ];
        $spfunction5 = [
            0x100,
            0x2080100,
            0x2080000,
            0x42000100,
            0x80000,
            0x100,
            0x40000000,
            0x2080000,
            0x40080100,
            0x80000,
            0x2000100,
            0x40080100,
            0x42000100,
            0x42080000,
            0x80100,
            0x40000000,
            0x2000000,
            0x40080000,
            0x40080000,
            0,
            0x40000100,
            0x42080100,
            0x42080100,
            0x2000100,
            0x42080000,
            0x40000100,
            0,
            0x42000000,
            0x2080100,
            0x2000000,
            0x42000000,
            0x80100,
            0x80000,
            0x42000100,
            0x100,
            0x2000000,
            0x40000000,
            0x2080000,
            0x42000100,
            0x40080100,
            0x2000100,
            0x40000000,
            0x42080000,
            0x2080100,
            0x40080100,
            0x100,
            0x2000000,
            0x42080000,
            0x42080100,
            0x80100,
            0x42000000,
            0x42080100,
            0x2080000,
            0,
            0x40080000,
            0x42000000,
            0x80100,
            0x2000100,
            0x40000100,
            0x80000,
            0,
            0x40080000,
            0x2080100,
            0x40000100,
        ];
        $spfunction6 = [
            0x20000010,
            0x20400000,
            0x4000,
            0x20404010,
            0x20400000,
            0x10,
            0x20404010,
            0x400000,
            0x20004000,
            0x404010,
            0x400000,
            0x20000010,
            0x400010,
            0x20004000,
            0x20000000,
            0x4010,
            0,
            0x400010,
            0x20004010,
            0x4000,
            0x404000,
            0x20004010,
            0x10,
            0x20400010,
            0x20400010,
            0,
            0x404010,
            0x20404000,
            0x4010,
            0x404000,
            0x20404000,
            0x20000000,
            0x20004000,
            0x10,
            0x20400010,
            0x404000,
            0x20404010,
            0x400000,
            0x4010,
            0x20000010,
            0x400000,
            0x20004000,
            0x20000000,
            0x4010,
            0x20000010,
            0x20404010,
            0x404000,
            0x20400000,
            0x404010,
            0x20404000,
            0,
            0x20400010,
            0x10,
            0x4000,
            0x20400000,
            0x404010,
            0x4000,
            0x400010,
            0x20004010,
            0,
            0x20404000,
            0x20000000,
            0x400010,
            0x20004010,
        ];
        $spfunction7 = [
            0x200000,
            0x4200002,
            0x4000802,
            0,
            0x800,
            0x4000802,
            0x200802,
            0x4200800,
            0x4200802,
            0x200000,
            0,
            0x4000002,
            0x2,
            0x4000000,
            0x4200002,
            0x802,
            0x4000800,
            0x200802,
            0x200002,
            0x4000800,
            0x4000002,
            0x4200000,
            0x4200800,
            0x200002,
            0x4200000,
            0x800,
            0x802,
            0x4200802,
            0x200800,
            0x2,
            0x4000000,
            0x200800,
            0x4000000,
            0x200800,
            0x200000,
            0x4000802,
            0x4000802,
            0x4200002,
            0x4200002,
            0x2,
            0x200002,
            0x4000000,
            0x4000800,
            0x200000,
            0x4200800,
            0x802,
            0x200802,
            0x4200800,
            0x802,
            0x4000002,
            0x4200802,
            0x4200000,
            0x200800,
            0,
            0x2,
            0x4200802,
            0,
            0x200802,
            0x4200000,
            0x800,
            0x4000002,
            0x4000800,
            0x800,
            0x200002,
        ];
        $spfunction8 = [
            0x10001040,
            0x1000,
            0x40000,
            0x10041040,
            0x10000000,
            0x10001040,
            0x40,
            0x10000000,
            0x40040,
            0x10040000,
            0x10041040,
            0x41000,
            0x10041000,
            0x41040,
            0x1000,
            0x40,
            0x10040000,
            0x10000040,
            0x10001000,
            0x1040,
            0x41000,
            0x40040,
            0x10040040,
            0x10041000,
            0x1040,
            0,
            0,
            0x10040040,
            0x10000040,
            0x10001000,
            0x41040,
            0x40000,
            0x41040,
            0x40000,
            0x10041000,
            0x1000,
            0x40,
            0x10040040,
            0x1000,
            0x41040,
            0x10001000,
            0x40,
            0x10000040,
            0x10040000,
            0x10040040,
            0x10000000,
            0x40000,
            0x10001040,
            0,
            0x10041040,
            0x40040,
            0x10000040,
            0x10040000,
            0x10001000,
            0x10001040,
            0,
            0x10041040,
            0x41000,
            0x41000,
            0x1040,
            0x1040,
            0x40040,
            0x10000000,
            0x10041000,
        ];
        $masks = [
            4294967295,
            2147483647,
            1073741823,
            536870911,
            268435455,
            134217727,
            67108863,
            33554431,
            16777215,
            8388607,
            4194303,
            2097151,
            1048575,
            524287,
            262143,
            131071,
            65535,
            32767,
            16383,
            8191,
            4095,
            2047,
            1023,
            511,
            255,
            127,
            63,
            31,
            15,
            7,
            3,
            1,
            0,
        ];

        //create the 16 or 48 subkeys we will need
        $keys = self::_createKeys($key);
        $m = 0;
        $len = strlen($message);
        $chunk = 0;
        //set up the loops for single and triple des
        $iterations = ((count($keys) == 32) ? 3 : 9); //single or triple des
        if (3 == $iterations) {
            $looping = (($encrypt) ? [0, 32, 2] : [30, -2, -2]);
        } else {
            $looping = (($encrypt) ? [0, 32, 2, 62, 30, -2, 64, 96, 2] : [94, 62, -2, 32, 64, 2, 30, -2, -2]);
        }

        $message .= (chr(0).chr(0).chr(0).chr(0).chr(0).chr(0).chr(0).chr(0)); //pad the message out with null bytes
        //store the result here
        $result = "";
        $tempresult = "";

        if (1 == $mode) {
            //CBC mode
            $cbcleft = (ord($iv{$m++}) << 24) | (ord($iv{$m++}) << 16) | (ord($iv{$m++}) << 8) | ord($iv{$m++});
            $cbcright = (ord($iv{$m++}) << 24) | (ord($iv{$m++}) << 16) | (ord($iv{$m++}) << 8) | ord($iv{$m++});
            $m = 0;
        }

        //loop through each 64 bit chunk of the message
        while ($m < $len) {
            $left = (ord($message{$m++}) << 24) | (ord($message{$m++}) << 16) | (ord($message{$m++}) << 8) | ord(
                    $message{$m++}
                );
            $right = (ord($message{$m++}) << 24) | (ord($message{$m++}) << 16) | (ord($message{$m++}) << 8) | ord(
                    $message{$m++}
                );

            //for Cipher Block Chaining mode, xor the message with the previous result
            if (1 == $mode) {
                if ($encrypt) {
                    $left ^= $cbcleft;
                    $right ^= $cbcright;
                } else {
                    $cbcleft2 = $cbcleft;
                    $cbcright2 = $cbcright;
                    $cbcleft = $left;
                    $cbcright = $right;
                }
            }

            //first each 64 but chunk of the message must be permuted according to IP
            $temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= ($temp << 4);
            $temp = (($left >> 16 & $masks[16]) ^ $right) & 0x0000ffff;
            $right ^= $temp;
            $left ^= ($temp << 16);
            $temp = (($right >> 2 & $masks[2]) ^ $left) & 0x33333333;
            $left ^= $temp;
            $right ^= ($temp << 2);
            $temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= ($temp << 8);
            $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);

            $left = (($left << 1) | ($left >> 31 & $masks[31]));
            $right = (($right << 1) | ($right >> 31 & $masks[31]));

            //do this either 1 or 3 times for each chunk of the message
            for ($j = 0; $j < $iterations; $j += 3) {
                $endloop = $looping[$j + 1];
                $loopinc = $looping[$j + 2];
                //now go through and perform the encryption or decryption
                for ($i = $looping[$j]; $i != $endloop; $i += $loopinc) {
                    //for efficiency
                    $right1 = $right ^ $keys[$i];
                    $right2 = (($right >> 4 & $masks[4]) | ($right << 28)) ^ $keys[$i + 1];
                    //the result is attained by passing these bytes through the S selection functions
                    $temp = $left;
                    $left = $right;
                    $right = $temp ^ ($spfunction2[($right1 >> 24 & $masks[24]) & 0x3f] | $spfunction4[($right1 >> 16 & $masks[16]) & 0x3f]
                            | $spfunction6[($right1 >> 8 & $masks[8]) & 0x3f] | $spfunction8[$right1 & 0x3f]
                            | $spfunction1[($right2 >> 24 & $masks[24]) & 0x3f] | $spfunction3[($right2 >> 16 & $masks[16]) & 0x3f]
                            | $spfunction5[($right2 >> 8 & $masks[8]) & 0x3f] | $spfunction7[$right2 & 0x3f]);
                }
                $temp = $left;
                $left = $right;
                $right = $temp; //unreverse left and right
            } //for either 1 or 3 iterations

            //move then each one bit to the right
            $left = (($left >> 1 & $masks[1]) | ($left << 31));
            $right = (($right >> 1 & $masks[1]) | ($right << 31));

            //now perform IP-1, which is IP in the opposite direction
            $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);
            $temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= ($temp << 8);
            $temp = (($right >> 2 & $masks[2]) ^ $left) & 0x33333333;
            $left ^= $temp;
            $right ^= ($temp << 2);
            $temp = (($left >> 16 & $masks[16]) ^ $right) & 0x0000ffff;
            $right ^= $temp;
            $left ^= ($temp << 16);
            $temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= ($temp << 4);

            //for Cipher Block Chaining mode, xor the message with the previous result
            if (1 == $mode) {
                if ($encrypt) {
                    $cbcleft = $left;
                    $cbcright = $right;
                } else {
                    $left ^= $cbcleft2;
                    $right ^= $cbcright2;
                }
            }
            $tempresult .= (chr($left >> 24 & $masks[24]).chr(($left >> 16 & $masks[16]) & 0xff).chr(
                    ($left >> 8 & $masks[8]) & 0xff
                ).chr($left & 0xff).chr($right >> 24 & $masks[24]).chr(($right >> 16 & $masks[16]) & 0xff).chr(
                    ($right >> 8 & $masks[8]) & 0xff
                ).chr($right & 0xff));

            $chunk += 8;
            if (512 == $chunk) {
                $result .= $tempresult;
                $tempresult = "";
                $chunk = 0;
            }
        } //for every 8 characters, or 64 bits in the message

        //return the result as an array
        return ($result.$tempresult);
    } //end of des

    /**
     * createKeys
     * this takes as input a 64 bit key (even though only 56 bits are used)
     * as an array of 2 integers, and returns 16 48 bit keys
     * @param string $key 加密key
     * @return array
     */
    private static function _createKeys($key)
    {
        //declaring this locally speeds things up a bit
        $pc2bytes0 = [
            0,
            0x4,
            0x20000000,
            0x20000004,
            0x10000,
            0x10004,
            0x20010000,
            0x20010004,
            0x200,
            0x204,
            0x20000200,
            0x20000204,
            0x10200,
            0x10204,
            0x20010200,
            0x20010204,
        ];
        $pc2bytes1 = [
            0,
            0x1,
            0x100000,
            0x100001,
            0x4000000,
            0x4000001,
            0x4100000,
            0x4100001,
            0x100,
            0x101,
            0x100100,
            0x100101,
            0x4000100,
            0x4000101,
            0x4100100,
            0x4100101,
        ];
        $pc2bytes2 = [
            0,
            0x8,
            0x800,
            0x808,
            0x1000000,
            0x1000008,
            0x1000800,
            0x1000808,
            0,
            0x8,
            0x800,
            0x808,
            0x1000000,
            0x1000008,
            0x1000800,
            0x1000808,
        ];
        $pc2bytes3 = [
            0,
            0x200000,
            0x8000000,
            0x8200000,
            0x2000,
            0x202000,
            0x8002000,
            0x8202000,
            0x20000,
            0x220000,
            0x8020000,
            0x8220000,
            0x22000,
            0x222000,
            0x8022000,
            0x8222000,
        ];
        $pc2bytes4 = [
            0,
            0x40000,
            0x10,
            0x40010,
            0,
            0x40000,
            0x10,
            0x40010,
            0x1000,
            0x41000,
            0x1010,
            0x41010,
            0x1000,
            0x41000,
            0x1010,
            0x41010,
        ];
        $pc2bytes5 = [
            0,
            0x400,
            0x20,
            0x420,
            0,
            0x400,
            0x20,
            0x420,
            0x2000000,
            0x2000400,
            0x2000020,
            0x2000420,
            0x2000000,
            0x2000400,
            0x2000020,
            0x2000420,
        ];
        $pc2bytes6 = [
            0,
            0x10000000,
            0x80000,
            0x10080000,
            0x2,
            0x10000002,
            0x80002,
            0x10080002,
            0,
            0x10000000,
            0x80000,
            0x10080000,
            0x2,
            0x10000002,
            0x80002,
            0x10080002,
        ];
        $pc2bytes7 = [
            0,
            0x10000,
            0x800,
            0x10800,
            0x20000000,
            0x20010000,
            0x20000800,
            0x20010800,
            0x20000,
            0x30000,
            0x20800,
            0x30800,
            0x20020000,
            0x20030000,
            0x20020800,
            0x20030800,
        ];
        $pc2bytes8 = [
            0,
            0x40000,
            0,
            0x40000,
            0x2,
            0x40002,
            0x2,
            0x40002,
            0x2000000,
            0x2040000,
            0x2000000,
            0x2040000,
            0x2000002,
            0x2040002,
            0x2000002,
            0x2040002,
        ];
        $pc2bytes9 = [
            0,
            0x10000000,
            0x8,
            0x10000008,
            0,
            0x10000000,
            0x8,
            0x10000008,
            0x400,
            0x10000400,
            0x408,
            0x10000408,
            0x400,
            0x10000400,
            0x408,
            0x10000408,
        ];
        $pc2bytes10 = [
            0,
            0x20,
            0,
            0x20,
            0x100000,
            0x100020,
            0x100000,
            0x100020,
            0x2000,
            0x2020,
            0x2000,
            0x2020,
            0x102000,
            0x102020,
            0x102000,
            0x102020,
        ];
        $pc2bytes11 = [
            0,
            0x1000000,
            0x200,
            0x1000200,
            0x200000,
            0x1200000,
            0x200200,
            0x1200200,
            0x4000000,
            0x5000000,
            0x4000200,
            0x5000200,
            0x4200000,
            0x5200000,
            0x4200200,
            0x5200200,
        ];
        $pc2bytes12 = [
            0,
            0x1000,
            0x8000000,
            0x8001000,
            0x80000,
            0x81000,
            0x8080000,
            0x8081000,
            0x10,
            0x1010,
            0x8000010,
            0x8001010,
            0x80010,
            0x81010,
            0x8080010,
            0x8081010,
        ];
        $pc2bytes13 = [0, 0x4, 0x100, 0x104, 0, 0x4, 0x100, 0x104, 0x1, 0x5, 0x101, 0x105, 0x1, 0x5, 0x101, 0x105];
        $masks = [
            4294967295,
            2147483647,
            1073741823,
            536870911,
            268435455,
            134217727,
            67108863,
            33554431,
            16777215,
            8388607,
            4194303,
            2097151,
            1048575,
            524287,
            262143,
            131071,
            65535,
            32767,
            16383,
            8191,
            4095,
            2047,
            1023,
            511,
            255,
            127,
            63,
            31,
            15,
            7,
            3,
            1,
            0,
        ];

        //how many iterations (1 for des, 3 for triple des)
        $iterations = ((strlen($key) >= 24) ? 3 : 1);
        //stores the return keys
        $keys = []; // size = 32 * iterations but you don't specify this in php
        //now define the left shifts which need to be done
        $shifts = [0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0];
        //other variables
        $m = 0;
        $n = 0;

        for ($j = 0; $j < $iterations; $j++) {
            //either 1 or 3 iterations
            $left = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++});
            $right = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++});

            $temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f;
            $right ^= $temp;
            $left ^= ($temp << 4);
            $temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff;
            $left ^= $temp;
            $right ^= ($temp << -16);
            $temp = (($left >> 2 & $masks[2]) ^ $right) & 0x33333333;
            $right ^= $temp;
            $left ^= ($temp << 2);
            $temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff;
            $left ^= $temp;
            $right ^= ($temp << -16);
            $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);
            $temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff;
            $left ^= $temp;
            $right ^= ($temp << 8);
            $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555;
            $right ^= $temp;
            $left ^= ($temp << 1);

            //the right side needs to be shifted and to get the last four bits of the left side
            $temp = ($left << 8) | (($right >> 20 & $masks[20]) & 0x000000f0);
            //left needs to be put upside down
            $left = ($right << 24) | (($right << 8) & 0xff0000) | (($right >> 8 & $masks[8]) & 0xff00) | (($right >> 24 & $masks[24]) & 0xf0);
            $right = $temp;

            //now go through and perform these shifts on the left and right keys
            for ($i = 0; $i < count($shifts); $i++) {
                //shift the keys either one or two bits to the left
                if ($shifts[$i] > 0) {
                    $left = (($left << 2) | ($left >> 26 & $masks[26]));
                    $right = (($right << 2) | ($right >> 26 & $masks[26]));
                } else {
                    $left = (($left << 1) | ($left >> 27 & $masks[27]));
                    $right = (($right << 1) | ($right >> 27 & $masks[27]));
                }
                $left = $left & -0xf;
                $right = $right & -0xf;

                //now apply PC-2, in such a way that E is easier when encrypting or decrypting
                //this conversion will look like PC-2 except only the last 6 bits of each byte are used
                //rather than 48 consecutive bits and the order of lines will be according to
                //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7
                $lefttemp = $pc2bytes0[$left >> 28 & $masks[28]] | $pc2bytes1[($left >> 24 & $masks[24]) & 0xf]
                    | $pc2bytes2[($left >> 20 & $masks[20]) & 0xf] | $pc2bytes3[($left >> 16 & $masks[16]) & 0xf]
                    | $pc2bytes4[($left >> 12 & $masks[12]) & 0xf] | $pc2bytes5[($left >> 8 & $masks[8]) & 0xf]
                    | $pc2bytes6[($left >> 4 & $masks[4]) & 0xf];
                $righttemp = $pc2bytes7[$right >> 28 & $masks[28]] | $pc2bytes8[($right >> 24 & $masks[24]) & 0xf]
                    | $pc2bytes9[($right >> 20 & $masks[20]) & 0xf] | $pc2bytes10[($right >> 16 & $masks[16]) & 0xf]
                    | $pc2bytes11[($right >> 12 & $masks[12]) & 0xf] | $pc2bytes12[($right >> 8 & $masks[8]) & 0xf]
                    | $pc2bytes13[($right >> 4 & $masks[4]) & 0xf];
                $temp = (($righttemp >> 16 & $masks[16]) ^ $lefttemp) & 0x0000ffff;
                $keys[$n++] = $lefttemp ^ $temp;
                $keys[$n++] = $righttemp ^ ($temp << 16);
            }
        } //for each iterations
        //return the keys we've created
        return $keys;
    } //end of des_createKeys

}


<?php

namespace Orbt\StyleMirror\Css;

use Orbt\StyleMirror\Resource\SingleUseQueue;
use Orbt\ResourceMirror\Resource\GenericResource;

/**
 * Scans a stylesheet for resources.
 */
class ResourceScanner
{
    /**
     * Regular expression pattern for matching relative paths referenced in CSS.
     */
    const PATH_PATTERN = '!url\(\s*[\'"]?([^\'"):/]+(?:/[^\'"):/]+)*)[\'"]?\s*\)!i';

    /**
     * Scanner queue.
     * @var SingleUseQueue
     */
    protected $queue;

    public function __construct(SingleUseQueue $queue)
    {
        $this->queue = $queue;
    }

    /**
     * Returns the queue used by this scanner.
     */
    public function getQueue()
    {
        return $this->queue;
    }

    /**
     * Scans CSS content for resources.
     *
     * @param GenericResource $resource
     * @param string $content
     */
    public function scan(GenericResource $resource, $content)
    {
        // Match all URL references.
        preg_match_all(self::PATH_PATTERN, $content, $matches);
        foreach ($matches[1] as $path) {
            try {
                $this->queue->add(new GenericResource($resource->resolvePath($path)));
            }
            catch (\InvalidArgumentException $e) {
                // Ignore unrecognized paths.
            }
        }
    }
}


<?php

/*
 * This file is part of the SmarTwig (Twig Extension).
 *
 * (c) Omar Yepez <omar.yepez@yepsua.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Yepsua\SmarTwig\Twig\Node;

use \Twig_Compiler;

/**
 *
 */
class SubMenuNode extends SimpleNode {

  /**
  * Compiles the node to PHP.
  *
  * @param Twig_Compiler A Twig_Compiler instance
  */
  public function compileWidget(Twig_Compiler $compiler){
    $compiler->addDebugInfo($this);
    $this->compileExtension($compiler);
    //if($this->getNode('values')->getNode('value') instanceof \Twig_Node_Expression_GetAttr ){
    if ($this->isIterable()) {
      $this->compileIteratorInitSintax($compiler);
        $this->compileInitWidget($compiler);
        $this->compileHtmlProperties($compiler);
        $this->buildId();
        $this->compileWidgetContents($compiler);
        $this->compileEndWidget($compiler);
      $this->compileIteratorEndSintax($compiler, $this->isValidateEmpty());
    }else{
      $this->compileInitWidget($compiler);
      $this->compileHtmlProperties($compiler);
      $this->compileWidgetContents($compiler);
      $this->compileEndWidget($compiler);
    }
  }

  public function compileInitWidget(Twig_Compiler $compiler){
    if($this->getNode('values')->hasNode('menuAttrs')){
        $compiler->write(sprintf('echo %s->initWidget(null,',$this->getVarName()));
        $compiler->subcompile($this->getNode('values')->getNode('menuAttrs'));
        $compiler->write(',"li");');
    }else{
        $compiler->write(sprintf('echo %s->initWidget(null,null,"li");',$this->getVarName()));
    }

    $compiler->raw("\n");
    $compiler->write(sprintf('echo %s->initWidget(',$this->getVarName()));
    $this->compileWidgetId($compiler);
    $compiler->raw(',');
  }

  public function compileEndWidget(Twig_Compiler $compiler){
    $compiler->write(sprintf('echo %s->endWidget("ul");',$this->getVarName()));
    $compiler->raw("\n");
    $compiler->write(sprintf('echo %s->endWidget("%s");',$this->getVarName(),$this->getTagName()));
    $compiler->raw("\n");
    $compiler->write(sprintf('echo %s->endWidget("li");',$this->getVarName()));
    $compiler->raw("\n");
  }

  public function compileHtmlProperties(Twig_Compiler $compiler, $args = array()){
    $this->compileStandardHtmlProperties($compiler);
    $compiler->write(sprintf(',"%s"',$this->getTagName()));

    if($this->getNode('values')->hasNode('label')){
       $compiler->write(',');
       $compiler->subcompile($this->getNode('values')->getNode('label'));
    }

    $compiler->write(');');
    $compiler->raw("\n");
    $compiler->write(sprintf('echo %s->initWidget(null,null,"ul");',$this->getVarName()));
    $compiler->raw("\n");
  }

  public function configureHTMLProperties(){
    return $this->getHTMLAttrs('optionWithoutLabel');
  }

  public function getWidgetName(){
    return 'html';
  }

  public function getTagName(){
    return 'a';
  }

  public function getSuffixId(){
    return $this->getTagName();
  }

  public function isIterableNode(){
    return true;
  }
}


<?php
/**
 * This file is part of the CarteBlanche PHP framework.
 *
 * (c) Pierre Cassat <me@e-piwi.fr> and contributors
 *
 * License Apache-2.0 <http://github.com/php-carteblanche/carteblanche/blob/master/LICENSE>
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CarteBlanche\Model;

/**
 * Helper functions for the IMAGE MODEL
 */
class ImageModelHelper
{

    /**
     */
    public static function getGps( $exifCoord, $hemi )
    {
        $degrees = count($exifCoord) > 0 ? self::gps2Num($exifCoord[0]) : 0;
        $minutes = count($exifCoord) > 1 ? self::gps2Num($exifCoord[1]) : 0;
        $seconds = count($exifCoord) > 2 ? self::gps2Num($exifCoord[2]) : 0;
        $flip = ($hemi == 'W' || $hemi == 'S') ? -1 : 1;
        return $flip * ($degrees + $minutes / 60 + $seconds / 3600);
    }

    /**
     */
    public static function gps2Num( $coordPart )
    {
        $parts = explode('/', $coordPart);
        if (count($parts) <= 0) return 0;
        if (count($parts) == 1) return $parts[0];
        return floatval($parts[0]) / floatval($parts[1]);
    }

    /**
     * La date est d'un format spécial, on va donc la rendre lisible
     */
    public static function getDateFromExif( $date )
    {
        $date_full = explode(":", current(explode(" ", $date)));
        $hour_full = explode(":", next(explode(" ", $date)));
        $year = current($date_full);
        $month = next($date_full);
        $day = next($date_full);
        $hour = current($hour_full);
        $minutes = next($hour_full);
        $seconds = next($hour_full);
        //	  return "$year-$month-$day $hour:$minutes:$seconds";
        return "$day-$month-$year ${hour}h$minutes:$seconds";
    }

}

// Endfile


<?php

/*
 * This file is part of the TecnoCreaciones package.
 *
 * (c) www.tecnocreaciones.com
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Tecnocreaciones\Vzla\GovernmentBundle\Twig\Extension;

/**
 * Description of CoreExtension
 *
 * @author Carlos Mendoza <inhack20@tecnocreaciones.com>
 */
class CoreExtension extends \Twig_Extension
{
    /**
     * @var \Twig_Environment
     */
    protected $environment;

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

    public function initRuntime(\Twig_Environment $environment)
    {
        $this->environment = $environment;
    }

    public function getFilters() {
        return array(
            new \Twig_SimpleFilter('hash', array($this, 'generateHash'), array('is_safe' => array('html'))),
        );
    }

    public function getFunctions() {
        return array(
            new \Twig_SimpleFunction('isRender', array($this,'isRender')),
        );
    }

    /**
     * Returns a list of functions to add to the existing list.
     *
     * @return array An array of functions
     */
    public function getTests()
    {
        return array(
                new \Twig_SimpleTest('loaded', [$this, 'hasExtension']),
        );
    }

//
//    function staticCall($class, $function, $args = array())
//    {
//        if (class_exists($class) && method_exists($class, $function))
//            return call_user_func_array(array($class, $function), $args);
//        return null;
//    }

    public function isRender($name)
    {
        if(in_array($name,$this->cacheRendered)){
            return true;
        }
        $this->cacheRendered[] = $name;
        return false;
    }

    function generateHash($str) {
        return md5($str);
    }

    /**
     * @param string $name
     * @return boolean
     */
    function hasExtension($name)
    {
        return $this->environment->hasExtension($name);
    }

    public function getName() {
        return 'vzla_government_core_extension';
    }
}


<?php

declare(strict_types=1);

/**
 * States.
 *
 * LICENSE
 *
 * This source file is subject to the MIT license and the version 3 of the GPL3
 * license that are bundled with this package in the folder licences
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to richarddeloge@gmail.com so we can send you a copy immediately.
 *
 *
 * @copyright   Copyright (c) 2009-2017 Richard Déloge (richarddeloge@gmail.com)
 *
 * @link        http://teknoo.software/states Project website
 *
 * @license     http://teknoo.software/license/mit         MIT License
 * @author      Richard Déloge <richarddeloge@gmail.com>
 */

namespace Teknoo\States\LifeCycle\StatedClass\Automated\Assertion;

use Teknoo\States\Proxy\ProxyInterface;

/**
 * Class Assertion
 * Implementation of AssertionInterface to determine states list from stated class instance's values.
 * All assertions defined with the method with() must be valid to get the assertion as valid.
 *
 * @copyright   Copyright (c) 2009-2017 Richard Déloge (richarddeloge@gmail.com)
 *
 * @link        http://teknoo.software/states Project website
 *
 * @license     http://teknoo.software/license/mit         MIT License
 * @author      Richard Déloge <richarddeloge@gmail.com>
 */
class Assertion extends AbstractAssertion implements AssertionInterface
{
    /**
     * @var array|callable
     */
    private $propertiesAssertions = [];

    /**
     * To register an assertion on a property. $exceptedValue can be the excepted value or a invokable object
     * Some invokable class are available in Teknoo\States\LifeCycle\StatedClass\Automated\Assertion\Property.
     *
     * @param string $property
     * @param mixed  $exceptedValue
     *
     * @return Assertion
     */
    public function with(string $property, $exceptedValue): Assertion
    {
        $this->propertiesAssertions[$property] = $exceptedValue;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function isValid(ProxyInterface $proxy): bool
    {
        $asserted = true;

        $reflectionObject = new \ReflectionObject($proxy);
        //Browse properties assertion
        foreach ($this->propertiesAssertions as $property => $exceptedValue) {
            if (null !== $exceptedValue && \property_exists($proxy, $property)) {
                //If the property exists, get it's value via the Reflection api
                // (properties are often not accessible for public)
                $reflectionProperty = $reflectionObject->getProperty($property);
                $reflectionProperty->setAccessible(true);
                $propertyValue = $reflectionProperty->getValue($proxy);

                if (!\is_callable($exceptedValue)) {
                    //Not a callable, perform a equal test
                    $asserted &= $exceptedValue == $propertyValue;
                } else {
                    $asserted &= $exceptedValue($propertyValue);
                }
            } else {
                //If the property does not existn the assertion fail
                $asserted = false;
            }

            if (!$asserted) {
                //Stop at first fail
                break;
            }
        }

        return !empty($asserted);
    }
}


<?php
namespace PlasmaConduit\option;
use PlasmaConduit\option\Option;
use PlasmaConduit\option\None;
use PlasmaConduit\either\Left;
use PlasmaConduit\either\Right;
use Exception;

class Some implements Option {

    private $_value;

    /**
     * This constructor is the only entry point where the value can be wrapped.
     * In other words, once a value is wrapped in a `Some` container it is
     * immutable within the container.
     *
     * @param mixed $value - The value to wrap
     */
    public function __construct($value) {
        $this->_value = $value;
    }

    /**
     * This function is used to signify if the Option type is empty. This is
     * the `Some` class and the class type carries this information so this
     * method will always return false.
     *
     * @return bool - Always false
     */
    public function isEmpty() {
        return false;
    }

    /**
     * This function is used to signify if the Option type is not empty. This
     * is the `Some` class and the class type carries this information so this
     * method will always return true.
     *
     * @return bool - Always true
     */
    public function nonEmpty() {
        return true;
    }

    /**
     * This returns the wrapped value.
     *
     * @return mixed - The wrapped value
     */
    public function get() {
        return $this->_value;
    }

    /**
     * This function will return the wrapped value if the `Option` type is
     * `Some` and if it's `None` it will return `$default` instead. Seeing how
     * this is the `Some` class, this will always return the wrapped value
     *
     * @param mixed $default - The default value if no value is present
     * @return mixed         - The wrapped value
     */
    public function getOrElse($default) {
        return $this->_value;
    }

    /**
     * This function takes an alternative `Option` type or callable and if
     * this `Option` type is `None` it returns the evalutated alternative type.
     * However, this is the `Some` class so it will always return itself.
     *
     * @param Callable|Option $alternative - The alternative Option
     * @return Option                      - Always returns itself
     * @throws Exception
     */
    public function orElse($alternative) {
        if (!is_callable($alternative) && !($alternative instanceof Option)) {
            throw new Exception(
                "Can't call Some#orElse() with non option or callable"
            );
        }
        return $this;
    }

    /**
     * For those moments when you just need either a value or null. This
     * function returns the wrapped value when called on the `Some` class and
     * returns null when called on the `None` class. This is the `Some` class
     * so it will always return the wrapped value
     *
     * @return mixed - The wrapped value or null
     */
    public function orNull() {
        return $this->_value;
    }

    /**
     * This returns the wrappd value as a `Left` projection.
     *
     * @param Callable|mixed $right - The alternative `Right` value
     * @return Either               - The `Left` projection
     */
    public function toLeft($right) {
        return new Left($this->get());
    }

    /**
     * This returns the wrapped value as a `Right` projection.
     *
     * @param Callable|mixed$left - The alternative `Left` value
     * @return Either             - The `Right` projection
     */
    public function toRight($left) {
        return new Right($this->get());
    }

    /**
     * This method takes a callable type (closure, function, etc) and if it's
     * called on a `Some` instance it will call the function `$mapper` with the
     * wrapped value and the value returend by `$mapper` will be wrapped in a
     * new `Some` container and that new `Some` container will be returned. If
     * this is called on a `None` container, the function `$mapper` will never
     * be called and instead we return `None` immediately. This is the `Some`
     * class, so it will always call the function and always return `Some`.
     *
     * @param Callable $mapper - Function to call on the wrapped value
     * @return Option          - The newly produced Some
     * @throws Exception
     */
    public function map($mapper) {
        if (!is_callable($mapper)) {
            throw new Exception("Can't call Some#map with a non callable.");
        }
        return new Some($mapper($this->_value));
    }

    /**
     * This method takes a callable type that takes the wrapped value of the
     * current `Some` as it's arguments and returns an `Option` type. The
     * `Option` type returned by the passed in callable is returned by this
     * method
     *
     * @param Callable $flatMapper - Fuction to call on the wrapped value
     * @return Option              - The `Option` produced by the flat mapper
     * @throws Exception
     */
    public function flatMap($flatMapper) {
        if (!is_callable($flatMapper)) {
            throw new Exception("Can't call Some#flatMap with a non callable.");
        }
        $flatMapped = $flatMapper($this->_value);
        if (!($flatMapped instanceof Option)) {
            throw new Exception(
                "Function passed to Some#flatMap must retrun Option"
            );
        }
        return $flatMapped;
    }

    /**
     * This function takes a callable as a predicate that takes the wrapped
     * value of the current `Some` as it's argument. If the predicate returns
     * true the current `Some` is returned. If the predicate returns false
     * a new `None` is returned.
     *
     * @param Callable $predicate - The predicate to check the wrapped value
     * @return Option             - `Some` on success `None` on failure
     * @throws Exception
     */
    public function filter($predicate) {
        if (!is_callable($predicate)) {
            throw new Exception("Can't call Some#filter with a non callable.");
        }
        if ($predicate($this->_value)) {
            return $this;
        } else {
            return new None();
        }
    }

}


<?php

declare(strict_types=1);

namespace Ruwork\ObjectStore\TypeResolver;

use Ruwork\ObjectStore\Configurator\StoreConfiguratorInterface;
use Ruwork\ObjectStore\Type\StoreTypeInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class ResolvedStoreType implements ResolvedStoreTypeInterface
{
    private $name;
    private $type;
    private $requiredTypes;
    private $optionsResolver;

    /**
     * @param StoreTypeInterface[] $requiredTypes
     */
    public function __construct(string $name, StoreTypeInterface $type, array $requiredTypes)
    {
        $this->name = $name;
        $this->type = $type;
        $this->requiredTypes = $requiredTypes;
    }

    /**
     * {@inheritdoc}
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * {@inheritdoc}
     */
    public function getType(): StoreTypeInterface
    {
        return $this->type;
    }

    /**
     * {@inheritdoc}
     */
    public function getRequiredTypes(): iterable
    {
        return $this->requiredTypes;
    }

    /**
     * {@inheritdoc}
     */
    public function getOptionsResolver(): OptionsResolver
    {
        if (null !== $this->optionsResolver) {
            return $this->optionsResolver;
        }

        $resolver = new OptionsResolver();

        foreach ($this->requiredTypes as $requiredType) {
            $requiredType->configureOptions($resolver);
        }

        $this->type->configureOptions($resolver);

        return $this->optionsResolver = $resolver;
    }

    /**
     * {@inheritdoc}
     */
    public function configureStore(StoreConfiguratorInterface $configurator, array $options): void
    {
        foreach ($this->requiredTypes as $requiredType) {
            $requiredType->configureStore($configurator, $options);
        }

        $this->type->configureStore($configurator, $options);
    }
}


<?php
/**
 * This file is part of the Hephaistos project management API.
 *
 * As each files provides by the CSCFA, this file is licensed
 * under the MIT license.
 *
 * PHP version 5.6
 *
 * @category Caster
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
namespace CSDT\CollectionsBundle\CollectionHelper\Caster;

use CSDT\CollectionsBundle\CollectionHelper\HelperInterface\ArrayCasterInterface;
use CSDT\CollectionsBundle\CollectionInterfaces\ValueCollectionInterface;

/**
 * Value collection caster
 *
 * This class is used to cast array to ValueCollection type.
 *
 * @category Caster
 * @package  Hephaistos
 * @author   matthieu vallance <matthieu.vallance@cscfa.fr>
 * @license  MIT <https://opensource.org/licenses/MIT>
 * @link     http://cscfa.fr
 */
class ValueCollectionCaster implements ArrayCasterInterface
{

    /**
     * To collection
     *
     * This method cast an array into
     * a specific collection.
     *
     * @param array  $array The array to cast
     * @param string $class The class to render
     *
     * @throws LogicException if the given class is not supported
     * @return CollectionInterface
     */
    public function toCollection(array $array, $class)
    {
        $reflection = new \ReflectionClass($class);
        $collection = $reflection->newInstanceWithoutConstructor();

        if ($collection instanceof ValueCollectionInterface) {
            $collection->addAll(array_values($array));
            return $collection;
        }

        throw new \LogicException(
            sprintf("The ValueCollectionCaster does not support type %s", $class)
        );
    }

    /**
     * Support
     *
     * Return true if the array caster
     * support the given collection class.
     *
     * @param string $class The collection class name
     *
     * @return boolean
     */
    public function support($class)
    {
        return in_array(
            ValueCollectionInterface::class,
            class_implements($class)
        );
    }
}


<?php
/**
 * This file is part of the CarteBlanche PHP framework.
 *
 * (c) Pierre Cassat <me@e-piwi.fr> and contributors
 *
 * License Apache-2.0 <http://github.com/php-carteblanche/carteblanche/blob/master/LICENSE>
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CarteBlanche\Library;

use \CarteBlanche\Exception\RuntimeException;
use \CarteBlanche\Exception\InvalidArgumentException;

/**
 * @author  Piero Wbmstr <me@e-piwi.fr>
 */
class Callback
{

    protected $callback_response_type='reference';

    protected $callback_name;

    protected $callback_stack;

    protected $value;

    protected $fields;

    protected $result;

    /**
     * Construction of a new callback execution
     *
     * @param   mixed       $value
     * @param   null/array  $callback_stack
     * @param   string      $callback_type
     * @param   string      $callback_name
     * @param   array       $fields         The collection of fields where to search the callback stack
     * @throws  \CarteBlanche\Exception\InvalidArgumentException if the callback type can't be found
     * @throws  \CarteBlanche\Exception\InvalidArgumentException if the stack seems empty
     */
    public function __construct($value, $callback_stack = null, $callback_type = null, $callback_name = null, $fields = null)
    {
        $this->value = $value;
        if (!empty($callback_stack) || is_array($callback_stack))
            $this->callback_stack = $callback_stack;
        if (!empty($fields) || is_array($fields))
            $this->fields = $fields;
        if (!empty($callback_name) || is_string($callback_name))
            $this->callback_name = $callback_name;

        if (!empty($callback_type)) {
            $this->callback_response_type = $callback_type;
            $_meth = '_executeCallbackAs'.ucfirst($this->callback_response_type);
            if (!method_exists($this, $_meth) || !is_callable(array($this, $_meth)))
                throw new InvalidArgumentException(
                    sprintf('Unknown callback type "%s"!', $this->callback_response_type)
                );
        }

        if (empty($this->callback_stack)) {
            if (!empty($fields) && !empty($this->callback_name))
                $this->_getCallbackStack();
            else
                throw new InvalidArgumentException(
                    'Unknown callback stack to execute (missing the stack or the callback name and the fields list)!'
                );
        }

        $this->result = $this->_executeCallbackStack();
    }

    /**
     * @return  mixed
     */
    public function getResult()
    {
        return $this->result;
    }

    /**
     * @throws  \CarteBlanche\Exception\RuntimeException
     */
    protected function _getCallbackStack()
    {
        foreach($this->fields as $_field_name=>$_field) {
            $callback_stack = null;
            if ($_field instanceof \CarteBlanche\Library\AutoObject\Field) {
                $callback_stack = $_field->getCallbacksStack( $this->callback_name );
            } elseif (is_array($_field) && isset($_field['callbacks'])) {
                $callback_stack = isset($_field['callbacks'][$this->callback_name]) ?
                    $_field['callbacks'][$this->callback_name] : null;
            } else {
                throw new RuntimeException(
                    sprintf('Invalid field "%s" to execute callback "%s" (must be an array or a "Lib\AutoObject\Field" object)!',
                        $_field_name, $this->callback_name)
                );
            }

            if (!empty($callback_stack)) {
                $this->callback_stack = $callback_stack;
                if (is_callable(array($_field, 'getValue')))
                    $this->value = $_field->getValue();
                elseif (is_array($_field) && isset($_field['value']))
                    $this->value = $_field['value'];
            }
        }
    }

    /**
     * Execution of a callback array on an entry of the data array
     *
     * @return  mixed
     */
    protected function _executeCallbackStack()
    {
        if (!empty($this->callback_stack)) {
            $_meth = '_executeCallbackAs'.ucfirst($this->callback_response_type);
            foreach ($this->callback_stack as $_callback) {
                $response = $this->$_meth( $_callback, $this->value );
            }
            return $response;
        }
        return null;
    }

// --------------------
// Executors
// --------------------

    /**
     * Execution of one callback on a value returning it by reference
     *
     * @param   string  $fct            The function name to execute, it will be called passing the current value as first argument
     * @param   mixed   $entry_value    The entry value to execute the callback, passed by reference
     * @return  mixed
     */
    protected function _executeCallbackAsReference($fct, &$entry_value)
    {
        list($fct_name, $args) = $this->_parseCallbackFunctionName($fct);
        array_unshift($args, $entry_value);
        $entry_value = $this->_executeCallback($fct_name, $args);
        return $entry_value;
    }

    /**
     * Execution of one callback on a value
     *
     * @param   string  $fct            The function name to execute, it will be called passing the current value as first argument
     * @param   mixed   $entry_value    The entry value to execute the callback
     * @return  bool
     */
    protected function _executeCallbackAsBoolean($fct, $entry_value)
    {
        list($fct_name, $args) = $this->_parseCallbackFunctionName($fct);
        array_unshift($args, $entry_value);
        $response = $this->_executeCallback($fct_name, $args);
        if ($response==$entry_value)
            return true;
        return (bool) $response;
    }

// --------------------
// Utilities
// --------------------

    /**
     * Parse a function name for a callback extracting the arguments if so
     *
     * @param   string  $fct   The function name to parse
     * @return  array   An array composed of the function name to execute and the arguments array to pass
     */
    protected function _parseCallbackFunctionName($fct)
    {
        $fct_name = $fct;
        $args = array();

        // case "fct_name(arg1,arg2)"
        if (0!=preg_match('/^
            ([^\(]+)                # the function name
            \(                      # the opening parenthesis of arguments
                (?:
                    ([^\)]+)        # anything but a coma
                ){1,}               # 1 or more times
            \)                      # the closing parenthesis of arguments
        $/xi', $fct, $matches)) {
            $fct_name = $matches[1];
            $args = explode(',', $matches[2]);
        }

        return array($fct_name, $args);
    }

    /**
     * Execution of one callback on a value
     *
     * @param   string  $fct   The function name to execute
     * @param   array   $args  The arguments to pass to the function
     * @return  mixed   The result of the function execution on arguments
     * @throws  \CarteBlanche\Exception\RuntimeException in case of error
     */
    protected function _executeCallback($fct, $args)
    {
        if (function_exists($fct)) {
            try {
                $response = call_user_func_array($fct, $args);
                return $response;
            } catch (\Exception $e) {
                throw new RuntimeException($e->getMessage());
            }
        }
        return isset($args[0]) ? $args[0] : null;
    }

}

// Endfile