<?php

namespace FluentKit\SuperModel;

use Illuminate\Database\Eloquent\Model;
use Validator;
use Hash;

class SuperModel extends Model{

	/*
	 * SuperModel Atts
	 */

	public $rules = array(
		'global' => array(),
		'create' => array(),
		'update' => array()
	);

	public $messages  = array(
		'global' => array(),
		'create' => array(),
		'update' => array()
	);

	protected $attributes_schema = array();

	protected $sanitize_attributes = true;

	protected $autohash_attributes = true;

	protected $autoserialize_attributes = true;

	private $old_attributes = array();

	private $hashed_originals = array();

	private $samerule_originals = array();

	private $errors;

	/*
	 * SuperModel Atts End
	 */

	public static function boot() {
        parent::boot();

        self::creating(function($model){
        	$model->sanitizeAttributes();
        	return $model->validateCreate();
        });

        self::updating(function($model){
        	$model->sanitizeAttributes();
        	return $model->validateUpdate();
        });
    }

    //overload mutator check has __call doesnt work with method exists.
    public function hasSetMutator($key)
	{

		if($this->autohash_attributes){
	       	foreach($this->attributes_schema as $k => $value){
	       		if($value == 'hashed' && $k == $key){
	       			return true;
	       		}
	       	}
       	}

       	if($this->autoserialize_attributes){
	       	foreach($this->attributes_schema as $k => $value){
	       		if($value == 'array' && $k == $key || $value == 'object' && $k == $key){
	       			return true;
	       		}
	       	}
       	}

		return parent::hasSetMutator($key);
	}

	public function hasGetMutator($key)
	{

       	if($this->autoserialize_attributes){
	       	foreach($this->attributes_schema as $k => $value){
	       		if($value == 'array' && $k == $key || $value == 'object' && $k == $key){
	       			return true;
	       		}
	       	}
       	}

		return parent::hasGetMutator($key);
	}

    /**
     * Handle dynamic method calls into the method.
     * Overrided from {@link Eloquent} to implement recognition of the {@link $relationsData} array.
     *
     * @param  string $method
     * @param  array  $parameters
     * @return mixed
     */
    public function __call($method, $parameters) {
        if($this->autohash_attributes){
	       	foreach($this->attributes_schema as $key => $value){
	       		$method_name = 'set'.studly_case($key).'Attribute';
	       		if($value == 'hashed' && $method_name == $method){
	       			$this->hashed_originals[$key] = $parameters[0];
	       			$this->attributes[$key] = Hash::make($parameters[0]);
	       			return;
	       		}
	       	}
       	}

       	if($this->autoserialize_attributes){
	       	foreach($this->attributes_schema as $key => $value){
	       		$method_name = 'set'.studly_case($key).'Attribute';
	       		if($value == 'array' && $method_name == $method){
	       			$this->attributes[$key] = serialize( (array) $parameters[0]);
	       			return;
	       		}
	       		if($value == 'object' && $method_name == $method){
	       			$this->attributes[$key] = serialize( (object) $parameters[0]);
	       			return;
	       		}
	       		$method_name = 'get'.studly_case($key).'Attribute';
	       		if($value == 'array' && $method_name == $method || $value == 'object' && $method_name == $method){
	       			return unserialize($parameters[0]);
	       		}
	       	}
       	}

        return parent::__call($method, $parameters);
    }

    public function sanitizeAttributes(){

    	if(!$this->sanitize_attributes) return;

    	//remove none model atts
    	$this->old_attributes = $this->attributes;

    	$schema = $this->attributes_schema;

        if(!isset($schema[$this->getKeyName()])){
            $this->attributes_schema[$this->getKeyName()] = 'int';
            $schema = $this->attributes_schema;
        }

    	foreach($this->attributes as $key => $attribute){
    		if(!isset($schema[$key])){
    			unset($this->attributes[$key]);
    		}else{
    			$this->attributes[$key] = $this->sanitizeAttribute($attribute, $schema[$key]);
    		}
    	}
        /*
        foreach($this->rules as $scope => $fields){
            foreach($fields as $key => $rules){
                $rules = explode('|', $rules);
                if(in_array('confirmed', $rules)){
                    $this->attributes[$key.'_confirmation'] = $this->attributes[$key];
                }
            }
        }
        */
    }

    private function sanitizeAttribute( $value, $type = 'string'){
    	switch($type){
    		case 'int':
    			return (int) $value;
    		break;
    		case 'bool':
    			return (bool) $value;
    		break;
    		default:
    			return $value;
    		break;
    	}
    }

    //build custom messages array based on scope
    private function buildMessages( $scope = 'create' ){
    	$custom_messages = $this->messages['global'];
    	foreach($this->messages[$scope] as $key => $value){
    		$custom_messages[$key] = $value;
    	}
    	return $custom_messages;
    }

    //turn rules array into string based to make it much easier to proccess, must be done to make building scope rules easier
    private function normalizeRules(){
    	foreach($this->rules as $scope => $rules){
    		foreach($rules as $field => $rule){
    			if(is_array($rule)){
    				$this->rules[$scope][$field] = implode('|', $rule);
    			}
    		}
    	}
    }

    //auto add props to unique rules - allows you to define a custom rule with additional where clauses or builds from model info, this turns rules into array format, but later normalized to string based
    private function buildUniqueRules() {

		$rulescopes = $this->rules;

		foreach($rulescopes as $scope => &$rules){

	        foreach ($rules as $field => &$ruleset) {
	            // If $ruleset is a pipe-separated string, switch it to array
	            $ruleset = (is_string($ruleset))? explode('|', $ruleset) : $ruleset;

	            foreach ($ruleset as &$rule) {
					if (str_contains($rule, 'unique') && str_contains($rule, '{id}') == false) {
						$params = explode(',', $rule);

						$uniqueRules = array();

						// Append table name if needed
						$table = explode(':', $params[0]);
						if (count($table) == 1)
							$uniqueRules[1] = $this->table;
						else
							$uniqueRules[1] = $table[1];

						// Append field name if needed
						if (count($params) == 1)
							$uniqueRules[2] = $field;
						else
							$uniqueRules[2] = $params[1];

						$uniqueRules[3] = $this->getKey();
				        $uniqueRules[4] = $this->getKeyName();

						$rule = 'unique:' . implode(',', $uniqueRules);
					}elseif(str_contains($rule, 'unique') && str_contains($rule, '{id}')){
						$rule = str_replace('{id}', $this->getKey(), $rule);
					} // end if str_contains

	            } // end foreach ruleset
	        }

    	}

        $this->rules = $rulescopes;
    }

    private function buildIfDirtyRules() {

		$rulescopes = $this->rules;

		foreach($rulescopes as $scope => &$rules){

	        foreach ($rules as $field => &$ruleset) {
	            // If $ruleset is a pipe-separated string, switch it to array
	            $ruleset = (is_string($ruleset))? explode('|', $ruleset) : $ruleset;

	            foreach ($ruleset as &$rule) {
					if (str_contains($rule, '_if_dirty')) {
                        if($this->isDirty($field) || !$this->exists){
						  $rule = str_replace('_if_dirty', '', $rule);
                        }else{
                            $rule = '';
                        }
					}
	            } // end foreach ruleset
	        }
    	}
        $this->rules = $rulescopes;
    }

    private function buildValidationRules($scope = 'create'){
    	$this->buildUniqueRules();
        $this->buildIfDirtyRules();
    	$this->normalizeRules();
    	$rules = $this->rules['global'];
    	foreach($this->rules[$scope] as $key => $value){
    		if(isset($rules[$key])){
    			$rules[$key] .= '|'.$value;
    		}else{
    			$rules[$key] = $value;
    		}
    	}
    	return $rules;
    }

    //we merge the original input first for confirmed fields that are needed to check (as if not in the schema they get removed)
    //we then add the actual model values which replace any original values
    //and finally we replace actual values with none-hashed values if there are any (so validation is done on plain text versions of the fields)
    private function buildValidationValues(){
        return array_merge($this->old_attributes, $this->attributes, $this->hashed_originals);
    }

    //get validator based on scope
    private function getValidator($scope = 'create'){
    	$rules = $this->buildValidationRules($scope);

    	$custom_messages = $this->buildMessages($scope);

    	$validation_values = $this->buildValidationValues();

    	return Validator::make($validation_values, $rules, $custom_messages);
    }

    //pre save check (if desired) does the same job but doesnt attempt to save
    public function validates(){
    	if($this->exists){
    		return $this->validateUpdate();
    	}else{
    		return $this->validateCreate();
    	}
    }

    //check validation on new instance
    public function validateCreate(){

    	$validator = $this->getValidator('create');

    	if($validator->fails()){
    		$this->errors = $validator->messages();
    		return false;
    	}

    	return true;
    }

    //check validation on existing instance
    public function validateUpdate(){

    	$validator = $this->getValidator('update');

    	if($validator->fails()){
    		$this->errors = $validator->messages();
    		return false;
    	}

    	return true;
    }

    //get the errors bag
    public function errors(){
    	return $this->errors;
    }

}


<?php
/**
 * Created by PhpStorm.
 * User: sicmouse
 * Date: 2018/8/31
 * Time: 上午9:15
 */

namespace DdvPhp\DdvRestfulApi\Lib;

use \Closure;
use DdvPhp\DdvRestfulApi\Exception\RequestParseError;
use DdvPhp\DdvRestfulApi\Interfaces\HttpRequestStream as HttpRequestStreamInterfaces;
use DdvPhp\DdvRestfulApi\Interfaces\RequestContentParses;

class HttpRequestStream implements HttpRequestStreamInterfaces
{

    /**
     * Maximum acceptable packet size.
     *
     * @var int
     */
    public static $maxPackageSize = 10485760;
    /**
     * The supported HTTP methods
     * @var array
     */
    public static $methods = array('GET', 'POST', 'PUT', 'DELETE', 'HEAD', 'OPTIONS');
    public static $contentTypeParses = array(
        'multipart/form-data' => RequestContentMultipart::class,
        'text/x-www-form-urlencoded' => RequestContentUrlencoded::class,
        'application/x-www-form-urlencoded' => RequestContentUrlencoded::class,
    );
    /**
     * @var RequestContentParses|null
     */
    protected $contentTypeParse = null;
    /**
     * 写入临时缓冲区
     * @var string
     */
    protected $writeTempBuffer = '';
    /**
     * 头缓冲区
     * @var string
     */
    protected $headerBuffer = '';
    /**
     * 计算出头的长度
     * @var int|null
     */
    protected $headerLength = null;
    /**
     * 计算出内容长度
     * @var int|null
     */
    protected $contentLength = null;
    /**
     * 请求内容类型
     * @var null
     */
    protected $contentType = '';
    /**
     * 需要hash的列表
     * @var array
     */
    protected $contentHashKeys = array('md5');
    /**
     * 增量hash上下文
     * @var array
     */
    protected $contentHashCtxs = array();
    /**
     * 需要hash的结果
     * @var array
     */
    protected $contentHashRes = array();
    /**
     * 头初始化完毕
     * @var bool
     */
    protected $headerInited = false;
    /**
     * 内容初始化完毕
     * @var bool
     */
    protected $contentInited = false;
    /**
     * 分隔符
     * @var string
     */
    protected $boundary = '';
    /**
     * 原始头
     * @var array
     */
    protected $rawHeaders = array();
    /**
     * 头
     * @var array
     */
    protected $headers = array();
    /**
     * data
     * @var array
     */
    protected $parameters = array();
    /**
     * 上传文件集合
     * @var array
     */
    protected $files = array();
    /**
     * @var array
     */
    protected $server = array();
    /**
     * 回车 CRLF
     * @var string|null
     */
    protected $CRLF = null;
    /**
     * 保存写入缓冲区的地址
     * 如果为false将不保存
     * 如果为null将保存临时目录
     * 如果为true就保存到$writeBuffer
     * 字符串就保存到具体文件
     * @var bool
     */
    protected $writeBufferSavePath = false;

    /**
     * 解析完成时候的回调，这个会随重置方法调用而清空
     * @var array
     */
    protected $hookCompleteds = array();
    /**
     * 这个是请求监听，这个不会随重置方法调用而清空
     * @var array
     */
    protected $hookRequesteds = array();

    /**
     * HttpRequestStream constructor.
     */
    public function __construct()
    {
        // 回车 CRLF
        $this->CRLF = HttpCache::$CRLF;
        // 重置数据
        $this->reset();
    }

    public function reset()
    {
        // 清空回调钩子
        $this->hookCompleteds = array();
        // 写入临时缓冲区
        $this->writeTempBuffer = '';
        // 计算出头的长度
        $this->headerLength = null;
        // 计算出内容长度
        $this->contentLength = null;
        // 头初始化完毕
        $this->headerInited = false;
        // 内容初始化完毕
        $this->contentInited = false;
        // 分隔符
        $this->boundary = '';
        // 重置原始头
        $this->rawHeaders = array();
        // 重置头
        $this->headers = array();
        // 重置data
        $this->parameters = array();
        // 重置文件
        $this->files = array();
        // 服务解析
        $this->server = array(
            'QUERY_STRING' => '',
            'REQUEST_METHOD' => '',
            'REQUEST_URI' => '',
            'SERVER_PROTOCOL' => '',
            'SERVER_SOFTWARE' => 'ddvRestfulApi/' . '1.0',
            'SERVER_NAME' => '',
            'HTTP_HOST' => '',
            'HTTP_USER_AGENT' => '',
            'HTTP_ACCEPT' => '',
            'HTTP_ACCEPT_LANGUAGE' => '',
            'HTTP_ACCEPT_ENCODING' => '',
            'HTTP_COOKIE' => '',
            'HTTP_CONNECTION' => '',
            'CONTENT_TYPE' => '',
            'REMOTE_ADDR' => '',
            'REMOTE_PORT' => '0',
            'REQUEST_TIME' => time()
        );
        // 如果有，需要销毁
        if ($this->contentTypeParse instanceof RequestContentParses) {
            $this->contentTypeParse->destroy();
            $this->contentTypeParse = null;
        }
        // 返回链式调用
        return $this;
    }

    public function write($buffer)
    {
        if ($this->isHeaderInited()) {
            $this->parseContentChunk($buffer);
        } else {
            $this->parseHttpHeader($buffer);
        }
    }

    protected function parseContentChunk($buffer)
    {
        if (empty($this->contentTypeParse) || !($this->contentTypeParse instanceof RequestContentParses)) {
            // 解析写入临时缓冲区的内容
            $this->contentTypeParseInit();
        }
        if (isset($this->contentTypeParse) && $this->contentTypeParse instanceof RequestContentParses) {
            // 增量
            foreach ($this->contentHashKeys as $key) {
                // 如果有 hash
                if (!empty($this->contentHashCtxs[$key])) {
                    // 增量哈希
                    hash_update($this->contentHashCtxs[$key], $buffer);
                }
            }
            $this->contentTypeParse->write($buffer);
        }
    }

    protected function contentTypeParseInit()
    {
        $this->onCompleted(function () {
            // 生成请求头信息 - 触发请求
            $requestInfo = new RequestInfo($this->parameters, '', $this->files, $this->server, $this->getHeaders());
            $requestInfo->setContentHash($this->contentHashRes);
            $this->emitRequested($requestInfo);
            // 触发重置，注意，完成触发后会马上重置，迎接下一次请求
            $this->reset();
        });
        if ((empty($this->server['CONTENT_TYPE']) || empty($this->contentLength)) && empty($buffer)) {
            // 标记完成
            $this->contentInited = true;
            // 触发完成
            $this->emitCompleted();
            return;
        }
        // 增量
        foreach ($this->contentHashKeys as $key) {
            // 如果有 hash
            if (!empty($this->contentHashCtxs[$key])) {
                // 结束
                hash_final($this->contentHashCtxs[$key]);
            }
            // 初始化增量 hash 运算上下文
            $this->contentHashCtxs[$key] = hash_init($key);
            // 清空结果
            $this->contentHashRes[$key] = '';
        }
        $type = explode(';', $this->server['CONTENT_TYPE'], 2)[0];
        $className = static::$contentTypeParses[$type];
        $obj = null;
        //可以有更多的匹配方式
        if (class_exists($className)) {
            // 实例化
            $obj = new $className($this);
        }
        if ($obj instanceof RequestContentParses) {
            // 实例化
            $this->contentTypeParse = $obj;
            // 完成的时候
            $this->contentTypeParse->onCompleted(function () {
                // 增量
                foreach ($this->contentHashKeys as $key) {
                    // 如果有 hash
                    if ($this->contentHashCtxs[$key] !== null) {
                        $res = array();
                        // 增量哈希
                        $this->contentHashRes[$key] = hash_final($this->contentHashCtxs[$key], true);
                        $this->contentHashCtxs[$key] = null;
                    }
                }
                // 标记完成
                $this->contentInited = true;
                // 触发完成
                $this->emitCompleted();
            });
        } else {
            throw new RequestParseError('解析数据失败', 'Bad Reques', 400);
        }
        unset($obj, $className);
    }

    protected function parseHeader($bufferOrArray = array())
    {
        $rawArrays = array();
        $headers = array();
        if (is_string($bufferOrArray)) {
            $rawArrays = explode($this->CRLF, $bufferOrArray);
        } elseif (is_array($bufferOrArray)) {
            $rawArrays = $bufferOrArray;
        }
        foreach ($rawArrays as $content) {
            // \r\n\r\n 切割换号有可能会有空的内容
            if (empty($content)) {
                continue;
            }
            list($key, $value) = explode(':', $content, 2);
            $key = trim($key);
            $value = trim($value);
            $headers[$key] = $value;
        }

        return $headers;
    }

    protected function parseHttpHeader($buffer)
    {
        // 写入临时缓冲区
        $this->writeTempBuffer .= $buffer;
        if (strpos($this->writeTempBuffer, $this->CRLF . $this->CRLF)) {
            // 判断包装长度是否超过限制。
            if (strlen($this->writeTempBuffer) >= static::$maxPackageSize) {
                // 太大的头缓冲区
                throw new RequestParseError('Header Buffer too large', 'Bad Reques', 400);
            }
            list($headerBuffer, $buffer) = explode($this->CRLF . $this->CRLF, $this->writeTempBuffer, 2);

            $server = array();
            $this->baseInit($headerBuffer, $server);
            // 解析内容
            $this->parseContentChunk($buffer);
            unset($uri, $method, $protocol, $rawHeaders, $headerBuffer, $key, $value);
        }
        unset($buffer);
    }
    public function baseInit ($headers = array(), $server = array()) {
        if(is_string($headers)){
            if (empty($server)||!is_array($server)){
                $server = array();
            }
            // 保存头Buffer
            $this->headerBuffer = $headers;
            // 计算长度
            $this->headerLength = strlen($this->headerBuffer);
            // 获取原始头
            $this->rawHeaders = explode($this->CRLF, $this->headerBuffer);
            // 获取[请求方式,uri,协议]
            list($server['REQUEST_METHOD'], $server['REQUEST_URI'], $server['SERVER_PROTOCOL']) = explode(' ', $this->rawHeaders[0]);
            // 判断请求方式是在允许接收的里面
            if (static::$methods !== false && !in_array($server['REQUEST_METHOD'], static::$methods)) {
                throw new RequestParseError('Bad Reques', 'Bad Reques', 400);
            }
            // 解析头
            $this->headers = $this->parseHeader(array_slice($this->rawHeaders, 1));
            foreach ($this->headers as $key => $value) {
                $key = str_replace('-', '_', strtoupper($key));
                $server['HTTP_' . $key] = $value;
                switch ($key) {
                    // HTTP_HOST
                    case 'HOST':
                        $tmp = explode(':', $value);
                        $server['SERVER_NAME'] = $tmp[0];
                        if (isset($tmp[1])) {
                            $server['SERVER_PORT'] = $tmp[1];
                        }
                        unset($tmp);
                        break;
                    // content-type
                    case 'CONTENT_TYPE':
                        if (!preg_match('/boundary="?(\S+)"?/', $value, $match)) {
                            if ($pos = strpos($value, ';')) {
                                $server['CONTENT_TYPE'] = substr($value, 0, $pos);
                            } else {
                                $server['CONTENT_TYPE'] = $value;
                            }
                            unset($pos);
                        } else {
                            $server['CONTENT_TYPE'] = 'multipart/form-data';
                            $this->boundary = '--' . $match[1];
                        }
                        break;
                    case 'CONTENT_LENGTH':
                        $server['CONTENT_LENGTH'] = $value;
                        break;
                }
            }
        }else{
            if(empty($server)){
                throw new RequestParseError('server params error', 'SERVER_PARAMS_ERROR', 500);
            }
            // 计算长度
            $this->headerLength = 0;
        }
        if (empty($headers)||!is_array($headers)){
            $headers = array();
            foreach ($server as $name => $value)
            {
                if (substr($name, 0, 5) == 'HTTP_')
                {
                    $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
                }
            }
        }
        if (empty($this->contentLength)&&isset($server['CONTENT_LENGTH'])){
            $this->contentLength = $server['CONTENT_LENGTH'];
        }
        if (empty($this->contentLength)){
            foreach ($headers as $name => $value){
                if (strtolower($name)==='content-length'){
                    $this->contentLength = $value;
                }
            }
        }
        // 存储头
        $this->headers = $headers;
        // 存储server
        $this->server = array_merge($this->server, $server);
        // 头初始化完毕
        $this->headerInited = true;
        // 清空临时缓冲区
        $this->writeTempBuffer = '';
        return $this;
    }

    public function getContentLength()
    {
        // 检测头是否初始化完成
        $this->checkHeaderInited();
        if ($this->contentLength) {
            return (int)$this->contentLength;
        } else {
            return 0;
        }
    }

    public function isHeaderInited()
    {
        return $this->headerInited;
    }

    public function checkHeaderInited()
    {
        if (!$this->isHeaderInited()) {
            throw new RequestParseError('Header is not initialized', 'HEADER_IS_NOT_INITIALIZED', 400);
        }
    }

    public function getMultipartBoundary()
    {
        return $this->boundary;
    }

    public function setDatas($parameters)
    {
        $this->parameters = $parameters;
        return $this;
    }

    public function setFiles($files)
    {
        $this->files = $files;
        return $this;
    }

    public function getHeaders()
    {
        return $this->headers;
    }

    /**
     * 触发重置，注意，完成触发后会马上重置，迎接下一次请求
     * @param Closure $fn
     */
    public function onCompleted(Closure $fn)
    {
        if (isset($this->hookCompleteds) && !is_array($this->hookCompleteds)) {
            $this->hookCompleteds = [];
        }
        $this->hookCompleteds[] = $fn;
    }

    /**
     * 触发重置，注意，完成触发后会马上重置，迎接下一次请求
     * @param Closure $fn
     */
    public function onRequested(Closure $fn)
    {
        if (isset($this->hookRequesteds) && !is_array($this->hookRequesteds)) {
            $this->hookRequesteds = [];
        }
        $this->hookRequesteds[] = $fn;
    }

    protected function emitRequested(RequestInfo $requesteInfo)
    {
        if (is_array($this->hookRequesteds)) {
            $fns = $this->hookRequesteds;
            foreach ($fns as $fn) {
                if ($fn instanceof Closure) {
                    call_user_func($fn, $requesteInfo);
                }
            }
            unset($fns);
        }
        return $this;
    }

    protected function emitCompleted()
    {
        if (is_array($this->hookCompleteds)) {
            $fns = $this->hookCompleteds;
            foreach ($fns as $fn) {
                if ($fn instanceof Closure) {
                    $fn();
                }
            }
            unset($fns);
        }
        return $this;
    }

    public function setRemoteInfo($remoteAddress, $remotePort, $info = array())
    {
        $this->server['REMOTE_ADDR'] = $remoteAddress;
        $this->server['REMOTE_PORT'] = $remotePort;
        return $this;
    }
    public function destroy()
    {
        $this->reset();
        $this->hookCompleteds = null;
    }
}


<?php

namespace Dhii\Data\Object;

use ArrayAccess;
use OutOfRangeException;
use Exception as RootException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use stdClass;
use Traversable;
use Dhii\Util\String\StringableInterface as Stringable;
use InvalidArgumentException;

/**
 * Functionality for unsetting multiple keys at once.
 *
 * @since [*next-version*]
 */
trait UnsetManyCapableTrait
{
    /**
     * Unset data by keys.
     *
     * @since [*next-version*]
     *
     * @param string[]|int[]|float[]|bool[]|Stringable[]|stdClass|Traversable $keys The keys of data to unset.
     *
     * @throws InvalidArgumentException    If the list of keys is invalid.
     * @throws OutOfRangeException         If the internal store or one of the keys is invalid.
     * @throws NotFoundExceptionInterface  If one of the keys is not found.
     * @throws ContainerExceptionInterface If problem accessing the container.
     */
    protected function _unsetMany($keys)
    {
        $keys  = $this->_normalizeIterable($keys);
        $store = $this->_getDataStore();

        try {
            $this->_containerUnsetMany($store, $keys);
        } catch (InvalidArgumentException $e) {
            throw $this->_createOutOfRangeException($this->__('Invalid store'), null, $e, $store);
        }
    }

    /**
     * Retrieves a pointer to the data store.
     *
     * @since [*next-version*]
     *
     * @return array|ArrayAccess|stdClass The data store.
     */
    abstract protected function _getDataStore();

    /**
     * Unsets values with the specified keys on the given container.
     *
     * @since [*next-version*]
     *
     * @param array|ArrayAccess|stdClass                                      $container The writable container to unset the values on.
     * @param string[]|Stringable[]|bool[]|int[]|float[]|Traversable|stdClass $keys      The list keys to unset the values for.
     *
     * @throws InvalidArgumentException    If the container or the list of keys is invalid.
     * @throws OutOfRangeException         If one of the keys is invalid.
     * @throws NotFoundExceptionInterface  If one of the keys is not found.
     * @throws ContainerExceptionInterface If problem accessing the container.
     */
    abstract protected function _containerUnsetMany(&$container, $keys);

    /**
     * Normalizes an iterable.
     *
     * Makes sure that the return value can be iterated over.
     *
     * @since [*next-version*]
     *
     * @param mixed $iterable The iterable to normalize.
     *
     * @throws InvalidArgumentException If the iterable could not be normalized.
     *
     * @return array|Traversable|stdClass The normalized iterable.
     */
    abstract protected function _normalizeIterable($iterable);

    /**
     * Creates a new Out Of Range exception.
     *
     * @since [*next-version*]
     *
     * @param string|Stringable|null $message  The error message, if any.
     * @param int|null               $code     The error code, if any.
     * @param RootException|null     $previous The inner exception for chaining, if any.
     * @param mixed|null             $argument The value that is out of range, if any.
     *
     * @return OutOfRangeException The new exception.
     */
    abstract protected function _createOutOfRangeException(
        $message = null,
        $code = null,
        RootException $previous = null,
        $argument = null
    );

    /**
     * Translates a string, and replaces placeholders.
     *
     * @since [*next-version*]
     * @see   sprintf()
     *
     * @param string $string  The format string to translate.
     * @param array  $args    Placeholder values to replace in the string.
     * @param mixed  $context The context for translation.
     *
     * @return string The translated string.
     */
    abstract protected function __($string, $args = [], $context = null);
}


<?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

namespace amylian\yii\base\common;

/**
 * Provides easy property support
 *
 *
 * This trait provides easy access to get and set methods like member variables:
 *
 * It follows the following convention:
 * - Property-Getter methods MUST be named getXxx()
 * - Property-Setter methods MUST be named setXxx($vlaue)
 *
 * Calling Getters: $v = $myObject->myProperty is equal to
 * $v = $myObject->getMyProperty();
 *
 * Calling Setters: $myObject->myProperty = 'xxx' is equal
 * to$v = $myObject->setMyProperty('xxx')
 *
 * ATTENTION:In the case of an access to an unknown property an
 * exception of class
 *
 *
 *
 *
 * @author Andreas Prucha
 */
trait ṔropertyTrait
{
    /**
     * Checks if the property exists
     *
     * This function checks if a setter method and/or a getter method
     * is implemented for the property or the member variable is declared public
     *
     * @param string $propertyName
     * @return bool
     */

    protected function __propertyTraitHasProperty($propertyName)
    {
        // Check if getter or setter method exists
        if (method_exists($this, 'get'.$propertyName) || method_exists($this, 'set'.$propertyName)) {
            return true;
        }
        // Check if property is public
        try
        {
            $classReflection = new \ReflectionProperty(get_class($this), $propertyName);
            return $classReflection->isPublic();
        } catch (\ReflectionException $ex) {
            return false;
        }
    }

    /**
     * Checks if the property exists
     *
     * This function checks if a setter method and/or a getter method
     * is implemented for the property or the member variable is declared public
     *
     * @param string $propertyName
     * @return bool
     */
    public function hasProperty($propertyName)
    {
        return $this->__propertyTraitHasProperty($propertyName);
    }

    /**
     * Tries to call the Getter for a property
     *
     * @param type $propertyName
     * @return void
     * @throws UnknownPropertyException
     */
    public function __get($propertyName)
    {
        $methodName = 'get'.$propertyName;
        if (method_exists($this, $methodName)) {
            return $this->$methodName();
        } else {
            throw new UnknownPropertyException('Error getting property: "'.$propertyName.
                    '" in object of class. "'.get_class($this).' Getter "get'.ucfirst($propertyName).'" not implemented');
        }
    }

    /**
     * Tries to call the Setter for a property
     *
     * @param string $propertyName
     * @param mixed $value
     * @return void
     * @throws UnknownPropertyException
     */
    public function __set($propertyName, $value)
    {
        $methodName = 'set'.$propertyName;
        if (method_exists($this, $methodName)) {
            $this->$methodName($value);
        } else {
            throw new UnknownPropertyException('Error seting property: "'.$propertyName.
                    '" in object of class. "'.get_class($this).' Setter "set'. ucfirst($propertyName).'" not implemented');
        }
    }

    /**
     * Checks if the property is not null
     * @param type $propertyName
     */
    public function __isset($propertyName)
    {
        $methodName = 'get'.$propertyName;
        if (method_exists($this, $methodName)) {
            return ($this->$methodName() !== null);
        } else {
            return false;
        }
    }

    /**
     * Checks if the property is not null
     * @param string $propertyName
     */
    public function __unset($propertyName)
    {
        $methodName = 'set'.$propertyName;
        if (method_exists($this, $methodName)) {
            $this->$methodName(null);
        } else {
            throw new UnknownPropertyException('Error seting property: "'.$propertyName.
                    '" in object of class. "'.get_class($this).' Setter "set'. ucfirst($propertyName).'" not implemented');
        }
    }

}


<?php

namespace Asoc\Dadatata\Filter\Unoconv;

use Asoc\Dadatata\Exception\ProcessingFailedException;
use Asoc\Dadatata\Filter\DocumentOptions;
use Asoc\Dadatata\Filter\FilterInterface;
use Asoc\Dadatata\Filter\OptionsInterface;
use Asoc\Dadatata\Model\DocumentInterface;
use Asoc\Dadatata\Model\ImageInterface;
use Asoc\Dadatata\Model\TextInterface;
use Asoc\Dadatata\Model\ThingInterface;
use Asoc\Dadatata\Tool\Unoconv;
use Asoc\Dadatata\ToolInterface;
use Neutron\TemporaryFilesystem\TemporaryFilesystemInterface;

class Convert implements FilterInterface
{
    /**
     * @var \Asoc\Dadatata\ToolInterface|Unoconv
     */
    private $unoconv;
    /**
     * @var \Neutron\TemporaryFilesystem\TemporaryFilesystemInterface
     */
    private $tmpFs;
    /**
     * @var DocumentOptions
     */
    private $defaults;

    public function __construct(ToolInterface $unoconv, TemporaryFilesystemInterface $tmpFs)
    {
        $this->unoconv = $unoconv;
        $this->tmpFs   = $tmpFs;
    }

    /**
     * @param OptionsInterface $options
     */
    public function setOptions(OptionsInterface $options)
    {
        if (!($options instanceof DocumentOptions)) {
            $options = new DocumentOptions($options->all());
        }
        $this->defaults = $options;
    }

    /**
     * @param ThingInterface                                              $thing
     * @param string                                                      $sourcePath
     * @param \Asoc\Dadatata\Filter\OptionsInterface|null|DocumentOptions $options
     *
     * @throws \Asoc\Dadatata\Exception\ProcessingFailedException
     * @return array Paths to generated files
     */
    public function process(ThingInterface $thing, $sourcePath, OptionsInterface $options = null)
    {
        $tmpDir  = $this->tmpFs->createTemporaryDirectory();
        $tmpFile = $tmpDir.DIRECTORY_SEPARATOR.$thing->getKey();

        /** @var DocumentOptions $options */
        $options = $this->defaults->merge($options);

        $pb      = $this->unoconv->getProcessBuilder()
            ->format($options->getFormat())
            ->output($tmpFile)
            ->input($sourcePath);
        $process = $pb->getProcess();

        $code = $process->run();
        if ($code !== 0) {
            throw ProcessingFailedException::create(
                'Failed to convert document to PDF',
                $code,
                $process->getOutput(),
                $process->getErrorOutput()
            );
        }

        return [$tmpFile];
    }

    /**
     * @param ThingInterface $thing
     *
     * @return boolean
     */
    public function canHandle(ThingInterface $thing)
    {
        return $thing instanceof DocumentInterface
        || $thing instanceof ImageInterface
        || $thing instanceof TextInterface
        || $thing->getMime() === 'text/rtf'
        || $thing->getMime() === 'application/rtf';
    }
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa\Query
 * @author    Hong Zhang <phossa@126.com>
 * @copyright 2015 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa\Query\Clause;

/**
 * LimitTrait
 *
 * @package Phossa\Query
 * @author  Hong Zhang <phossa@126.com>
 * @see     LimitInterface
 * @version 1.0.0
 * @since   1.0.0 added
 */
trait LimitTrait
{
    /**
     * LIMIT
     *
     * @var    array
     * @access protected
     */
    protected $clause_limit = [];

    /**
     * {@inheritDoc}
     */
    public function limit(/*# int */ $count, /*# int */ $offset = 0)
    {
        if ($count || $offset) {
            if (!empty($this->clause_limit)) {
                $this->clause_limit[0] = (int) $count;
            } else {
                $this->clause_limit = [(int) $count, (int) $offset];
            }
        }
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function offset(/*# int */ $offset)
    {
        if (!empty($this->clause_limit)) {
            $this->clause_limit[1] = (int) $offset;
        } else {
            $this->clause_limit = [ 0, (int) $offset];
        }
        return $this;
    }

    /**
     * {@inheritDoc}
     */
    public function page(/*# int */ $pageNumber, /*# int */ $perPage = 30)
    {
        $this->clause_limit = [(int) $perPage, ($pageNumber - 1) * $perPage];
        return $this;
    }

    /**
     * Build LIMIT
     *
     * @return array
     * @access protected
     */
    protected function buildLimit()/*# : array */
    {
        $result = [];
        if (!empty($this->clause_limit)) {
            $res = [];

            if ($this->clause_limit[0]) {
                $res[] = 'LIMIT ' . $this->clause_limit[0];
            }

            if ($this->clause_limit[1]) {
                $res[] = 'OFFSET ' . $this->clause_limit[1];
            }

            if (!empty($res)) {
                $result[] = join(' ', $res);
            }
        }
        return $result;
    }
}


<?php
/*
 * Copyright (c) 2014 @trashtoy
 * https://github.com/trashtoy/
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
 * Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
/**
 * PHP class file.
 * @auhtor trashtoy
 * @since  2.0.0
 */
namespace Peach\Util;

/**
 * {@link ArrayMap} の entryList() から生成されるオブジェクトです.
 */
class ArrayMapEntry extends AbstractMapEntry
{
    /**
     * このエントリーが登録されている ArrayMap です.
     * @var ArrayMap
     */
    private $map;

    /**
     * 新しい ArrayMapEntry を構築します.
     *
     * @param mixed    $key   キー
     * @param mixed    $value キーに関連づけられた値
     * @param ArrayMap $map   このエントリーが属する ArrayMap
     */
    public function __construct($key, $value, ArrayMap $map)
    {
        parent::__construct($key, $value);
        $this->map = $map;
    }

    /**
     * このエントリーの値を更新します.
     * @param mixed $value 新しくセットされる値
     */
    public function setValue($value)
    {
        $this->map->put($this->key, $value);
        $this->value = $value;
    }

    /**
     * この MapEntry の文字列表現です.
     * @return string
     */
    public function __toString()
    {
        return "[{$this->key}={$this->value}]";
    }
}


<?php
/**
 * Created by PhpStorm.
 * User: janhuang
 * Date: 15/6/22
 * Time: 上午11:04
 * Github: https://www.github.com/janhuang
 * Coding: https://www.coding.net/janhuang
 * SegmentFault: http://segmentfault.com/u/janhuang
 * Blog: http://segmentfault.com/blog/janhuang
 * Gmail: bboyjanhuang@gmail.com
 * WebSite: http://www.janhuang.me
 */

namespace FastD\Debug;

use FastD\Debug\Collectors\Collector;
use FastD\Debug\Feature\ConfigCollector;
use FastD\Debug\Feature\FdbCollector;
use FastD\Debug\Theme\Symfony\StyleSheet;
use FastD\Debug\Theme\Theme;
use Monolog\Logger;
use ErrorException;
use Throwable;
use Exception;

/**
 * Class Debug
 *
 * @package FastD\Debug
 */
class Debug
{
    use ConfigCollector, FdbCollector;

    /**
     * @var static
     */
    protected static $handler;

    /**
     * @var Logger
     */
    protected $logger;

    /**
     * 依赖第三方组件: maximebf/debugbar
     *
     * @var DebugBar
     */
    protected $bar = null;

    /**
     * @var Collector[]
     */
    protected $collectors = [];

    /**
     * @var Theme|StyleSheet
     */
    protected $theme = StyleSheet::class;

    /**
     * @var bool
     */
    protected $display = true;

    /**
     * @var bool
     */
    protected $booted = false;

    /**
     * @var bool
     */
    protected $cliMode = false;

    /**
     * Debug constructor.
     *
     * @param bool $display
     * @param Logger|null $logger
     */
    protected function __construct($display = true, Logger $logger = null)
    {
        if ('cli' === PHP_SAPI) {
            ini_set('display_errors', 0);
        } elseif (!ini_get('log_errors') || ini_get('error_log')) {
            ini_set('display_errors', 1);
        }

        $this->display = $display;

        $this->logger = $logger;

        $this->cliMode = 'cli' === PHP_SAPI ? true : false;
    }

    /**
     * @return bool
     */
    public function isBooted()
    {
        return $this->booted;
    }

    /**
     * @return bool
     */
    public function isDisplay()
    {
        return $this->display;
    }

    /**
     * @return bool
     */
    public function isCliMode()
    {
        return $this->cliMode;
    }

    /**
     * @param Logger $logger
     * @return $this
     */
    public function setLogger(Logger $logger)
    {
        $this->logger = $logger;

        return $this;
    }

    /**
     * @return Logger|null
     */
    public function getLogger()
    {
        return $this->logger;
    }

    /**
     * @param $theme
     * @return $this
     * @throws ErrorException
     */
    public function setTheme($theme)
    {
        if (!($theme instanceof Theme)) {
            throw new ErrorException(sprintf('Debug theme must be instance ["%s"]', Theme::class));
        }

        $this->theme = $theme;

        return $this;
    }

    /**
     * @return Theme
     */
    public function getTheme()
    {
        return $this->theme;
    }

    /**
     * @return DebugBar
     */
    public function getBar()
    {
        return $this->bar;
    }

    /**
     * @param $data
     * @return $this
     */
    public function dump($data)
    {
        if (!$this->bar) {
            return $this;
        }

        $this->bar->getCollector('dumper')->addMessage($data);

        return $this;
    }

    /**
     * @param bool $display
     * @param Logger|null $logger
     * @return Debug
     */
    public static function getHandler($display = true, Logger $logger = null)
    {
        if (null === static::$handler) {
            static::$handler = new static($display, $logger);
        }

        return static::$handler;
    }

    /**
     * @param bool $display
     * @param Logger|null $logger
     * @param array $collectors
     * @return Debug
     */
    public static function enable($display = true, Logger $logger = null, array $collectors = DebugBar::PRESET_COLLECTORS)
    {
        $handler = static::getHandler($display, $logger);

        if ($handler->isBooted()) {
            return $handler;
        }

        // 捕捉一切异常与错误
        static::enableError($handler);

        static::enableException($handler);

        if ($handler->isDisplay() && !$handler->isCliMode()) {
            static::enableDebugBar($collectors);
        }

        return $handler;
    }

    /**
     * @param Debug|null $debug
     * @return void
     */
    protected static function enableError(Debug $debug = null)
    {
        $handler = null === $debug ? static::getHandler() : $debug;

        register_shutdown_function([$handler, 'handleFatalError']);

        if ($prev = set_error_handler([$handler, 'handleError'])) {
            restore_error_handler();
            set_error_handler([$handler, 'handleError']);
        }

        unset($prev, $handler);
    }

    /**
     * @param Debug|null $debug
     * @return void
     */
    protected static function enableException(Debug $debug = null)
    {
        $handler = null === $debug ? static::getHandler() : $debug;

        if ($prev = set_exception_handler([$handler, 'handleException'])) {
            restore_exception_handler();
            set_exception_handler([$handler, 'handleException']);
        }

        unset($prev, $handler);
    }

    /**
     * @param array $collectors
     */
    protected static function enableDebugBar(array $collectors = DebugBar::PRESET_COLLECTORS)
    {
        $handler = static::getHandler();

        $handler->bar = new DebugBar($collectors);
    }

    /**
     * 将错误托管給 exception(handleException) 处理。
     *
     * @param $code
     * @param $message
     * @param $file
     * @param $line
     * @throws ErrorException
     */
    public function handleError($code, $message, $file, $line)
    {
        throw new ErrorException($message, $code, E_ERROR, $file, $line);
    }

    /**
     * 将错误托管給 exception(handleException) 处理。
     *
     * @throws ErrorException
     */
    public function handleFatalError()
    {
        if (($error = error_get_last()) && $error['type'] == E_ERROR) {
            self::handleError($error['type'], $error['message'], $error['file'], $error['line']);
        } else if ($this->bar instanceof DebugBar && $this->isDisplay()) {
            // Shutdown script running.
            // If enable debug mode. Can be auto show debugbar into html page.
            $this->bar->output();
        }
    }

    /**
     * 抛给 Wrapper 对象处理
     *
     * @param Throwable $throwable
     * @return void
     */
    public function handleException(Throwable $throwable)
    {
        if (null !== $this->bar) {
            // Compatible `addException(\Exception $e)`
            if (!($throwable instanceof Exception)) {
                $throwable = new ErrorException(
                    $throwable->getMessage(),
                    $throwable->getCode(),
                    E_ERROR,
                    $throwable->getFile(),
                    $throwable->getLine()
                );
            }
            $this->getBar()->getCollector('exceptions')->addException($throwable);
        }

        $this->wrapper($throwable);
    }

    /**
     * @param Throwable $throwable
     * @return void
     */
    public function wrapper(Throwable $throwable)
    {
        Wrapper::output($this, $throwable);
    }
}


<?php
/**
 * AnimeDb package.
 *
 * @author    Peter Gribanov <info@peter-gribanov.ru>
 * @copyright Copyright (c) 2014, Peter Gribanov
 * @license   http://opensource.org/licenses/MIT
 */

namespace AnimeDb\Bundle\CacheTimeKeeperBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class AnimeDbCacheTimeKeeperExtension extends Extension
{
    /**
     * @param array $configs
     * @param ContainerBuilder $container
     */
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
        $loader->load('parameters.yml');
        $loader->load('services.yml');

        $configuration = new Configuration(
            $container->getParameter('cache_time_keeper.driver.shmop.salt'),
            $container->getParameter('cache_time_keeper.driver.file.path')
        );
        $config = $this->processConfiguration($configuration, $configs);

        $config = $this->mergeBackwardCompatibilityConfig($config, $container);
        $config = $this->mergeDefaultConfig($config, $container);

        // set params from config
        $container->setParameter('cache_time_keeper.enable', $config['enable']);
        $container->setParameter('cache_time_keeper.etag.algorithm', $config['etag_hasher']['algorithm']);
        $container->setParameter('cache_time_keeper.private_headers', $config['private_headers']);
        $container->setParameter('cache_time_keeper.track.clear_cache', $config['track']['clear_cache']);
        $container->setParameter('cache_time_keeper.track.individually', $config['track']['individually_entity']);
        $container->setParameter('cache_time_keeper.driver.shmop.salt', $config['drivers']['shmop']['salt']);
        $container->setParameter('cache_time_keeper.driver.file.path', $config['drivers']['file']['path']);
        $container->setParameter('cache_time_keeper.driver.memcache.prefix', $config['drivers']['memcache']['prefix']);

        // configure memcache
        $memcache = $container->getDefinition('cache_time_keeper.memcache');
        foreach ($config['drivers']['memcache']['hosts'] as $host) {
            $memcache->addMethodCall('addServer', $host);
        }

        // add service aliases
        $container->setAlias(
            'cache_time_keeper.driver',
            $this->getRealServiceName($config['use_driver'])
        );
        $container->setAlias(
            'cache_time_keeper.driver.multi.fast',
            $this->getRealServiceName($config['drivers']['multi']['fast'])
        );
        $container->setAlias(
            'cache_time_keeper.driver.multi.slow',
            $this->getRealServiceName($config['drivers']['multi']['slow'])
        );
        $container->setAlias('cache_time_keeper.cache_key_builder.etag_hasher', $config['etag_hasher']['driver']);
    }

    /**
     * @param string $name
     *
     * @return string
     */
    protected function getRealServiceName($name)
    {
        if (strpos($name, '.') === false) {
            return 'cache_time_keeper.driver.'.$name;
        }

        return $name;
    }

    /**
     * @param array $config
     * @param ContainerBuilder $container
     *
     * @return array
     */
    protected function mergeBackwardCompatibilityConfig(array $config, ContainerBuilder $container)
    {
        if ($container->hasParameter('cache_time_keeper.driver')) {
            $config['use_driver'] = $container->getParameter('cache_time_keeper.driver');
        }

        foreach (['fast', 'slow'] as $item) {
            if (empty($config['drivers']['multi'][$item]) &&
                $container->hasParameter('cache_time_keeper.driver.multi.'.$item)
            ) {
                $config['drivers']['multi'][$item] = $container->getParameter('cache_time_keeper.driver.multi.'.$item);
            }
        }

        return $config;
    }

    /**
     * @param array $config
     * @param ContainerBuilder $container
     *
     * @return array
     */
    protected function mergeDefaultConfig(array $config, ContainerBuilder $container)
    {
        $config = array_merge([
            'enable' => true,
            'use_driver' => 'file',
            'private_headers' => ['Authorization', 'Cookie'],
            'etag_hasher' => [],
            'track' => [],
            'drivers' => [],
        ], $config);

        $config['etag_hasher'] = array_merge([
            'driver' => 'cache_time_keeper.cache_key_builder.default_etag_hasher',
            'algorithm' => 'sha256',
        ], $config['etag_hasher']);

        $config['track'] = array_merge([
            'clear_cache' => true,
            'individually_entity' => false,
        ], $config['track']);

        $config['drivers'] = array_merge([
            'multi' => [
                'fast' => 'shmop',
                'slow' => 'file',
            ],
            'shmop' => [
                'salt' => $container->getParameter('cache_time_keeper.driver.shmop.salt'),
            ],
            'file' => [
                'path' => $container->getParameter('cache_time_keeper.driver.file.path'),
            ],
            'memcache' => [
                'prefix' => 'cache_time_keeper_',
                'hosts' => [],
            ],
        ], $config['drivers']);

        return $config;
    }
}


<?php

/*
 * This file is part of the kaloa/util package.
 *
 * For full copyright and license information, please view the LICENSE file
 * that was distributed with this source code.
 */

namespace Kaloa\Util;

use ArrayObject as CoreArrayObject;

/**
 * Adds grouping and multi-dimensional sorting functions to ArrayObject
 *
 * See: http://www.ermshaus.org/2010/03/php-kaloa-spl-arrayobject
 *
 * Please note: This class isn't the most efficient way to perform the
 * implemented operations. A more low-level approach to grouping will be
 * considerably faster and use less resources, sorting operations should be done
 * in the DMBS (if applicable).
 */
final class ArrayObject extends CoreArrayObject
{
    /**
     * Adds possibility to pass multi-dimensional arrays to the constructor
     *
     * All arrays found among the values of the passed array will be transformed
     * recursively to instances of ArrayObject.
     *
     * @param array $array Data array to initialize class with
     */
    public function __construct(array $array)
    {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $array[$key] = new self($value);
            }
        }

        parent::__construct($array);
    }

    /**
     * Groups the array by one or more criteria defined via callback function
     *
     * Each element in the first dimension of the array is passed to the
     * specified callback function and will be reordered in regard to the
     * returned value. This can either be a string with the new key or an array
     * with a stack of new keys. For an element <var>$e</var>, the callback
     * return value <var>array('a', 'b')</var> translates to
     * <var>$newArray['a']['b'][] = $e;</var>.
     *
     * Callback functions may take the element argument by reference and modify
     * it during execution (e. g. to remove any fields that will be grouped by).
     *
     * @param  callback $func Function to group by
     * @return ArrayObject Provides fluent interface
     */
    public function groupBy($func)
    {
        $ret = array();
        $it  = $this->getIterator();

        while ($it->valid()) {

            if (is_object($it->current())) {
                $key = call_user_func($func, $it->current());
            } else {
                // Pass scalar values by reference, too
                $value = $it->current();
                $key = call_user_func_array($func, array(&$value));
                $it->offsetSet($it->key(), $value);
                unset($value);
            }

            if (is_array($key)) {
                $ref = &$ret;

                foreach ($key as $subkey) {
                    if (!array_key_exists($subkey, $ref)) {
                        $ref[$subkey] = array();
                    }
                    $ref = &$ref[$subkey];
                }
                $ref[] = $it->current();
            } else {
                $ret[$key][] = $it->current();
            }

            $it->next();
        }
        unset($ref);

        $ret = new self($ret);
        $this->exchangeArray($ret->getArrayCopy());

        return $this;
    }

    /**
     * Adds usort as an instance method
     *
     * @param callback $cmp_function Function to sort by
     * @return boolean
     */
    public function usort($cmp_function)
    {
        $tmp = $this->getArrayCopy();
        $ret = usort($tmp, $cmp_function);

        $tmp = new self($tmp);
        $this->exchangeArray($tmp->getArrayCopy());

        return $ret;
    }

    /**
     *
     * @param  array|callback $funcs
     * @return ArrayObject Provides fluent interface
     */
    public function usortm($funcs)
    {
        return $this->_uxsortm($funcs);
    }

    /**
     *
     *
     * @param  array|callback $funcs
     * @return ArrayObject Provides fluent interface
     */
    public function uasortm($funcs)
    {
        return $this->_uxsortm($funcs, 'a');
    }

    /**
     *
     * @param  array|callback $funcs
     * @return ArrayObject Provides fluent interface
     */
    public function uksortm($funcs)
    {
        return $this->_uxsortm($funcs, 'k');
    }

    /**
     * Returns the multi-dimensional array structure with all instances of
     * ArrayObject transformed to standard PHP arrays
     *
     * @return array Flattened array
     */
    public function getArrayCopyRec()
    {
        $ret = array();
        $it  = $this->getIterator();

        while ($it->valid()) {
            if ($it->current() instanceof self) {
                $ret[$it->key()] = $it->current()->getArrayCopyRec();
            } else {
                $ret[$it->key()] = $it->current();
            }

            $it->next();
        }

        return $ret;
    }

    /**
     * Recursively applies all provided sorting functions to their corresponding
     * dimension of the array
     *
     * @param ArrayObject $a         Represents the current dimension
     *        in the active array branch
     * @param array                 $sortFuncs Holds the specified sorting
     *        function for each dimension
     * @param int                   $depth     Current dimension
     * @param string                $sortMode  Possible values: 'a', 'k', ''
     *        (= uasort, uksort, usort)
     */
    private function _uxsortmRec(
        ArrayObject $a,
        array $sortFuncs,
        $depth = 0,
        $sortMode = ''
    ) {
        $goOn = (count($sortFuncs) > $depth + 1);
        $it   = $a->getIterator();

        while ($it->valid()) {
            if (null !== $sortFuncs[$depth]) {
                if ($sortMode == 'a') {
                    $it->current()->uasort($sortFuncs[$depth]);
                } else if ($sortMode == 'k') {
                    $it->current()->uksort($sortFuncs[$depth]);
                } else {
                    $it->current()->usort($sortFuncs[$depth]);
                }
            }

            if ($goOn) {
                $this->_uxsortmRec(
                    $it->current(),
                    $sortFuncs,
                    $depth + 1,
                    $sortMode
                );
            }

            $it->next();
        }
    }

    /**
     * Applies the first sorting function (if set) to the array's first
     * dimension and starts the recursion to apply the other functions (if set)
     *
     * A sorting function is exactly the same as an usort callback. If you don't
     * want to sort a specific dimension but one or more dimensions below it,
     * pass <var>null</var> for each dimension that should be skipped.
     * <var>array(null, null, $func)</var> would sort the third dimension but
     * leave dimensions one and two untouched.
     *
     * @param  array|callback $funcs    Sorting function(s) to sort one or more
     *         dimensions of the array by
     * @param  string         $sortMode Possible values: 'a', 'k', '' (= uasort,
     *         uksort, usort)
     * @return ArrayObject Provides fluent interface
     */
    private function _uxsortm($funcs, $sortMode = '')
    {
        if (!is_array($funcs)) {
            $funcs = array($funcs);
        }

        if (count($funcs) > 0) {
            if (null !== $funcs[0]) {
                if ($sortMode == 'a') {
                    $this->uasort($funcs[0]);
                } else if ($sortMode == 'k') {
                    $this->uksort($funcs[0]);
                } else {
                    $this->usort($funcs[0]);
                }
            }

            if (count($funcs) > 1) {
                $this->_uxsortmRec($this, $funcs, 1, $sortMode);
            }
        }

        return $this;
    }
}


<?php
namespace Apatis\Transporter;

use Apatis\Exceptions\InvalidArgumentException;
use GuzzleHttp\Client;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\CookieJarInterface;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Uri;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;

/**
 * Class AbstractTransport
 * @package Apatis\Transporter
 *
 * @method static AbstractTransport connect(string $url, array $config = [])
 * @method static AbstractTransport copy(string $url, array $config = [])
 * @method static AbstractTransport delete(string $url, array $config = [])
 * @method static AbstractTransport get(string $url, array $config = [])
 * @method static AbstractTransport head(string $url, array $config = [])
 * @method static AbstractTransport link(string $url, array $config = [])
 * @method static AbstractTransport lock(string $url, array $config = [])
 * @method static AbstractTransport options(string $url, array $config = [])
 * @method static AbstractTransport post(string $url, array $config = [])
 * @method static AbstractTransport put(string $url, array $config = [])
 * @method static AbstractTransport purge(string $url, array $config = [])
 * @method static AbstractTransport patch(string $url, array $config = [])
 * @method static AbstractTransport propFind(string $url, array $config = [])
 * @method static AbstractTransport trace(string $url, array $config = [])
 * @method static AbstractTransport unlink(string $url, array $config = [])
 * @method static AbstractTransport unlock(string $url, array $config = [])
 * @method static AbstractTransport view(string $url, array $config = [])
 */
abstract class AbstractTransport implements TransportInterface
{
    /**
     * Current Method
     *
     * @var string
     */
    protected $method = TransportInterface::DEFAULT_METHOD;

    /**
     * Use as Common Browsers
     *
     * @var array
     */
    protected $configs_default = [
        'headers' => [
            'User-Agent' => [TransportUtil::DEFAULT_USER_AGENT],
        ],
        'timeout'         => 10,
        'allow_redirects' => true,
    ];

    /**
     * @var array|CookieJar
     */
    protected $configs = [];

    /**
     * @var RequestInterface
     */
    protected $request;

    /**
     * @var TransportResponse
     */
    protected $last_response;

    /**
     * @var Client
     */
    protected $client;

    /**
     * @var string
     */
    protected $currentParamType = self::PARAM_FORM;

    /**
     * @var bool
     */
    protected $inProcessingLoop = false;

    /**
     * AbstractTransport constructor.
     *
     * @param string $uri   the url to get
     * @param array $config array configuration
     */
    public function __construct($uri, array $config = [])
    {
        $this->inProcessingLoop = false;
        if (is_string($uri)) {
            $config['base_uri'] = $uri;
        }

        /**
         * Just Manipulate
         */
        $this->configs = array_merge($this->configs_default, $config);
        // roll headers to default
        if (!is_array($this->configs['headers'])) {
            $this->configs['headers'] = $this->configs_default['headers'];
        }
        foreach ($this->configs['headers'] as $key => $value) {
            $key = $this->normalizeHeaderName($key);
            if (!$key) {
                unset($this->configs['headers'][$key]);
            }
            if (!is_array($value)) {
                $this->configs['headers'][$key] = [$value];
            }
        }

        $this->request = new Request($this->method, $uri);
        $this->client  = new Client($this->configs);
    }

    /**
     * Normalize Real Header Name
     *
     * @param string $keyName Header Name key, The key will be convert into
     *                        First Character after `-`(dash) into uppercase
     *                        And space will be replace as `dash`
     * @return null|string
     */
    protected function normalizeHeaderName($keyName)
    {
        if (!is_string($keyName)) {
            return null;
        }

        return ucwords(trim(strtolower($keyName)), '-') ?: null;
    }
    /**
     * Replace Headers Value
     *
     * @param array $headers collection headers array
     * @return static
     */
    public function replaceHeaders(array $headers)
    {
        foreach ($headers as $key => $value) {
            $this->setHeader($key, $value);
        }
        return $this;
    }

    /**
     * Replace Headers Value
     *
     * @param array $headers collection headers array
     * @return static
     */
    public function removeHeaders(array $headers)
    {
        $this->inProcessingLoop = true;
        foreach ($headers as $value) {
            if (is_string($value) || is_numeric($value)) {
                unset($this->configs['headers'][$value]);
            }
        }

        $this->inProcessingLoop = false;
        return $this->buildConfigClient();
    }

    /**
     * Remove Existing Header
     *
     * @param string $name
     * @return static
     */
    public function removeHeader($name)
    {
        return $this->removeHeaders([$name]);
    }

    /**
     * Set Header
     *
     * @param string $keyName Header Name key, The key will be convert into
     *                        First Character after `-`(dash) into uppercase
     *                        And space will be replace as `dash`
     * @param string $value
     * @return static
     */
    public function setHeader($keyName, $value)
    {
        $keyName = $this->normalizeHeaderName($keyName);
        if (!$keyName) {
            return $this;
        }

        if (!isset($this->configs['headers'])) {
            $this->configs['headers'] = [];
        }

        $this->configs['headers'][$keyName] = [$value];
        if (!$this->inProcessingLoop) {
            return $this
                ->buildConfigClient()
                ->withRequest($this->request->withHeader($keyName, $value));
        }

        return $this
            ->withRequest($this->request->withHeader($keyName, $value));
    }

    /**
     * Method Allowed
     *
     * @param string $method
     * @return bool|string the method
     */
    public static function allowedMethod($method)
    {
        if (is_string($method) && ($method = strtoupper(trim($method))) != '') {
            return defined(static::class . '::METHOD_'. $method) ? $method : false;
        }

        return false;
    }

    /**
     * Build Config Client
     *
     * @return static
     */
    protected function buildConfigClient()
    {
        $this->client = new Client($this->configs);
        return $this;
    }

    /**
     * Set Config
     *
     * @param mixed $name
     * @param mixed $value
     * @return static
     */
    public function setConfig($name, $value)
    {
        if ($name == self::PARAM_FORM || $name == self::PARAM_MULTIPART) {
            return $this;
        }

        if ($name == 'headers' || $name == self::PARAM_FORM || $name == self::PARAM_MULTIPART) {
            if (is_array($value)) {
                $obj = $name == 'headers'
                    ? $this->withHeaders($value)
                    : $this->withParams($value, $name);
                $this->configs = $obj->configs;
                $this->client  = $obj->client;
                $this->request = $obj->request;
            }

            return $this;
        }

        $this->configs[$name] = $value;
        return $this->buildConfigClient();
    }

    /**
     * Get Config
     *
     * @param null|string $name
     * @return array|mixed|null
     */
    public function getConfig($name = null)
    {
        return is_null($name)
            ? $this->configs
            : (isset($this->configs[$name]) ? $this->configs[$name] : null);
    }

    /**
     * @return Client
     */
    public function getClient()
    {
        return $this->client;
    }

    /**
     * @return \Exception|ResponseInterface
     */
    public function getResponse()
    {
        return ! $this->last_response instanceof TransportResponse
            ? $this->send()->getResponse()
            : $this->last_response->getResponse();
    }

    /**
     * @return TransportResponse
     */
    public function getLastResponse()
    {
        return $this->last_response;
    }

    /**
     * @param Client $client
     * @return static
     */
    public function withClient(Client $client)
    {
        $object = clone $this;
        $object->client = $client;
        $this->configs  = $client->getConfig();
        return $object;
    }

    /**
     * With Set Headers
     *
     * @param array $headers
     * @return static
     */
    public function withHeaders(array $headers)
    {
        $object = clone $this;
        $object->configs['headers'] = [];
        $object->inProcessingLoop = true;
        $object->replaceHeaders($headers);
        $object->inProcessingLoop = true;
        return $object->buildConfigClient();
    }

    /**
     * With Added Current Headers
     *
     * @param array $headers
     * @return static
     */
    public function withAddedHeaders(array $headers)
    {
        $object = clone $this;
        $object->inProcessingLoop = false;
        $object->configs['headers'] = [];
        foreach ($headers as $keyName => $value) {
            $keyName = $this->normalizeHeaderName($keyName);
            if (!$keyName) {
                continue;
            }

            if (!isset($this->configs['headers'])) {
                $object->configs['headers'] = [];
            }

            $object->configs['headers'][$keyName] = !is_array($value) ? [$value] : $value;
            $object->request = $object->request->withAddedHeader($keyName, $value);
        }

        return $object->buildConfigClient();
    }

    /**
     * With Added Current Headers
     *
     * @param mixed $header
     * @return static
     */
    public function withoutHeader($header)
    {
        $object = clone $this;
        $headerName = $object->normalizeHeaderName($header);
        if (isset($this->configs['headers'][$headerName])) {
            unset($this->configs['headers'][$headerName]);
        }

        $object->request = $object->request->withoutHeader($headerName);
        return $object->buildConfigClient();
    }

    /**
     * @param CookieJarInterface $cookieJar
     * @return static
     */
    public function withCookieJar(CookieJarInterface $cookieJar)
    {
        $object = clone $this;
        $object->configs['cookies'] = $cookieJar;
        return $object->buildConfigClient();
    }

    /**
     * @param array $cookie
     * @param string $domain
     * @return static
     */
    public function withCookieArray(array $cookie, $domain = null)
    {
        $object = clone $this;
        $object->configs['cookies'] = $domain
            ? CookieJar::fromArray($cookie, $domain)
            : new CookieJar(false, $cookie);
        return $object->buildConfigClient();
    }

    /**
     * Without Send Cookie
     *
     * @param string|array $cookieName
     * @return static
     */
    public function withoutCookie($cookieName = null)
    {
        $object = clone $this;
        if (! $this->configs['cookies'] instanceof CookieJarInterface) {
            return $object;
        }

        if (!$cookieName) {
            unset($object->configs['cookies']);
        } else {
            if (!is_array($cookieName)) {
                $cookieName = [$cookieName];
            }
            $cookies = $this->configs['cookies']->toArray();
            foreach ($cookieName as $cookie) {
                if (!is_string($cookie) || !$cookie) {
                    continue;
                }
                unset($cookies[$cookie]);
            }

            $this->configs['cookies'] = new CookieJar($cookies);
        }

        return $object->buildConfigClient();
    }

    /**
     * With Params
     *
     * @param array $params array parameter to set
     * @param string $type default use TransportInterface::PARAM_FORM
     * @return static
     * @throws InvalidArgumentException
     */
    public function withParams(array $params = [], $type = null)
    {
        $object = clone $this;
        if (!$type && isset($this->configs[$this->currentParamType])) {
            $type = $this->currentParamType;
        }

        if (! $type && (
            isset($this->configs[self::PARAM_FORM]) || isset($this->configs[self::PARAM_MULTIPART]))
        ) {
            $type = isset($object->configs[self::PARAM_FORM])
                ? self::PARAM_FORM
                : (
                isset($object->configs[self::PARAM_MULTIPART])
                    ? self::PARAM_MULTIPART
                    : $type
                );
        }

        $type = $type ?: self::PARAM_FORM;
        $object->setParamType($type);
        $object->configs[$type] = $params;
        return $object->buildConfigClient();
    }

    /**
     * Remove All existing Parameter
     *
     * @param  string|null $paramName
     * @return static
     */
    public function withoutParam($paramName = null)
    {
        $object = clone $this;
        if (is_null($paramName)) {
            unset($object->configs[$this->currentParamType]);
        } else {
            if (isset($object->configs[$this->currentParamType])) {
                if (!is_array($object->configs[$this->currentParamType])) {
                    unset($object->configs[$this->currentParamType]);
                } else {
                    if (is_array($paramName)) {
                        $paramName = [$paramName];
                    }
                    foreach ($paramName as $paramKey) {
                        if (is_string($paramKey) || is_numeric($paramKey)) {
                            unset($object->configs[$this->currentParamType][$paramName]);
                        }
                    }
                }
            }
        }

        return $object->buildConfigClient();
    }

    /**
     * Set Parameter
     *
     * @param string $name
     * @param mixed $value
     * @return static
     */
    public function setParam($name, $value)
    {
        if (!isset($this->configs[$this->currentParamType])) {
            $this->configs[$this->currentParamType] = [];
        }

        $this->configs[$this->currentParamType][$name] = $value;
        if (!$this->inProcessingLoop) {
            return $this->buildConfigClient();
        }

        return $this;
    }

    /**
     * Set Params
     *
     * @param array $params
     * @return static
     */
    public function setParams(array $params)
    {
        $this->configs[$this->currentParamType] = [];
        return $this->replaceParams($params);
    }

    /**
     * Set Params
     *
     * @param array $params
     * @return static
     */
    public function replaceParams(array $params)
    {
        if (!isset($this->configs[$this->currentParamType])) {
            $this->configs[$this->currentParamType] = [];
        }

        $this->inProcessingLoop = true;
        foreach ($params as $key => $paramValue) {
            $this->setParam($key, $paramValue);
        }

        $this->inProcessingLoop = false;

        return $this->buildConfigClient();
    }

    /**
     * Set Param Type
     *
     * @param string $type
     * @return static
     * @throws InvalidArgumentException
     */
    public function setParamType($type)
    {
        if (! is_string($type) || ! in_array($type, [self::PARAM_MULTIPART, self::PARAM_FORM])
        ) {
            throw new InvalidArgumentException(
                sprintf(
                    "Invalid parameter form type, form type only allowed $1s and $2s",
                    self::PARAM_FORM,
                    self::PARAM_MULTIPART
                ),
                E_USER_ERROR
            );
        }

        $this->currentParamType = $type;
        $reverse_params = $type == self::PARAM_FORM
            ? self::PARAM_MULTIPART
            : self::PARAM_FORM;
        $reverse_params_value = isset($this->configs[$reverse_params])
            ? $this->configs[$reverse_params]
            : null;
        $params_value = isset($this->configs[$type])
            ? $this->configs[$type]
            : null;
        unset(
            $this->configs[self::PARAM_FORM],
            $this->configs[self::PARAM_MULTIPART]
        );

        $this->configs[$type] = is_array($reverse_params_value)
            ? $reverse_params_value
            : (is_array($params_value) ? $params_value : []);

        return $this->buildConfigClient();
    }

    /**
     * With URI
     *
     * @param string|UriInterface $uri
     * @return static
     * @throws InvalidArgumentException
     */
    public function withUri($uri)
    {
        if (! $uri instanceof UriInterface) {
            if (!is_string($uri)) {
                throw new InvalidArgumentException(
                    sprintf(
                        'Parameter uri must be as string or instance of %s',
                        UriInterface::class
                    ),
                    E_USER_ERROR
                );
            }

            $uri = new Uri($uri);
        }
        $object = clone $this;
        return $this
            ->buildConfigClient()
            ->withRequest($object->request->withUri($uri));
    }

    /**
     * With Set Request
     *
     * @param RequestInterface $request
     * @return mixed
     */
    public function withRequest(RequestInterface $request)
    {
        $object = clone $this;
        $object->request = $request;
        $object->method  = $request->getMethod();
        return $object;
    }

    /**
     * With Method
     *
     * @param string $method GET|PUT|HEAD|POST ... etc
     *                       fallback to default
     *
     * @return static
     * @throws InvalidArgumentException
     */
    public function withMethod($method)
    {
        $object = clone $this;
        /**
         *  Check available Method
         */
        $old_method  = $method;
        if (($method = $object->allowedMethod($method)) === false || !is_string($method)) {
            settype($old_method, 'string');
            throw new InvalidArgumentException(
                sprintf(
                    'Method %s is not Allowed!',
                    $old_method
                ),
                E_USER_ERROR
            );
        }

        return $object->withRequest(
            $object->request->withMethod($method)
        );
    }

    /**
     * @return TransportResponse
     */
    public function send()
    {
        try {
            $this->last_response = new TransportResponse(
                $this->client->send($this->request, $this->configs)
            );
        } catch (\Exception $e) {
            $this->last_response = new TransportResponse($e);
        }

        return $this->last_response;
    }

    /**
     * Call Static Method
     *
     * @param string $name      Method
     * @param array  $arguments Argument array
     * @return mixed
     * @throws InvalidArgumentException
     */
    public static function __callStatic($name, array $arguments)
    {
        if (empty($arguments)) {
            throw new InvalidArgumentException(
                'Arguments Could not be empty',
                E_USER_ERROR
            );
        }

        $arguments = array_values($arguments);
        if (!is_string($arguments[0]) && ! $arguments[0] instanceof UriInterface) {
            throw new InvalidArgumentException(
                sprintf(
                    'Argument 1 must be as a string %s or %s given',
                    UriInterface::class,
                    gettype($arguments[0])
                ),
                E_USER_ERROR
            );
        }

        $config = [];
        if (isset($arguments[1])) {
            if (!is_array($arguments[1])) {
                throw new InvalidArgumentException(
                    sprintf(
                        'Argument 2 must be as a array %s or %s given',
                        UriInterface::class,
                        gettype($arguments[1])
                    ),
                    E_USER_ERROR
                );
            }

            $config = $arguments[1];
        }

        $class = new static($arguments[0], $config);

        return $class->withMethod($name);
    }

    /**
     * Magic Method
     *
     * @param string $method
     * @param array  $arguments
     * @return static
     * @throws InvalidArgumentException
     */
    public function __call($method, array $arguments)
    {
        if (empty($arguments)) {
            throw new \InvalidArgumentException(
                'Arguments Could not be empty',
                E_USER_ERROR
            );
        }

        $arguments = array_values($arguments);
        if (!is_string($arguments[0]) && ! $arguments[0] instanceof UriInterface) {
            throw new InvalidArgumentException(
                sprintf(
                    'Argument 1 must be as a string %s or %s given',
                    UriInterface::class,
                    gettype($arguments[0])
                ),
                E_USER_ERROR
            );
        }

        if (isset($arguments[1]) && !is_array($arguments[1])) {
            throw new InvalidArgumentException(
                sprintf(
                    'Argument 2 must be as an array %s given',
                    gettype($arguments[1])
                ),
                E_USER_ERROR
            );
        }

        $transport = $this->withMethod($method)->withUri($arguments[0]);
        if (isset($arguments[1])) {
            foreach ($arguments[1] as $key => $value) {
                $transport->setConfig($key, $value);
            }
        }

        return $transport;
    }

    /**
     * @return string
     */
    public function __toString()
    {
        return ! $this->last_response instanceof TransportResponse
            ? $this->send()->getResponseBodyString()
            : $this->last_response->getResponseBodyString();
    }
}


<?php
//
// +---------------------------------------------------------------------+
// | CODE INC. SOURCE CODE                                               |
// +---------------------------------------------------------------------+
// | Copyright (c) 2017 - Code Inc. SAS - All Rights Reserved.           |
// | Visit https://www.codeinc.fr for more information about licensing.  |
// +---------------------------------------------------------------------+
// | NOTICE:  All information contained herein is, and remains the       |
// | property of Code Inc. SAS. The intellectual and technical concepts  |
// | contained herein are proprietary to Code Inc. SAS are protected by  |
// | trade secret or copyright law. Dissemination of this information or |
// | reproduction of this material  is strictly forbidden unless prior   |
// | written permission is obtained from Code Inc. SAS.                  |
// +---------------------------------------------------------------------+
//
// Author:   Joan Fabrégat <joan@codeinc.fr>
// Date:     26/04/2018
// Time:     17:23
// Project:  Psr15Middlewares
//
declare(strict_types=1);
namespace CodeInc\Psr15Middlewares\HttpHeaders\Security;
use CodeInc\Psr15Middlewares\HttpHeaders\AbstractHttpHeaderMiddleware;
use CodeInc\Psr15Middlewares\MiddlewareException;
use CodeInc\Psr15Middlewares\Tests\HttpHeaders\Security\XssProtectionMiddlewareTest;

/**
 * Class XssProtectionMiddleware
 *
 * @link https://developer.mozilla.org/docs/Web/HTTP/Headers/X-XSS-Protection
 * @see XssProtectionMiddlewareTest
 * @package CodeInc\Psr15Middlewares\HttpHeaders\Security
 * @author Joan Fabrégat <joan@codeinc.fr>
 */
class XssProtectionMiddleware extends AbstractHttpHeaderMiddleware
{
    /**
     * @var bool
     */
    private $enableProtection;

    /**
     * @var bool
     */
    private $blockMode = false;

    /**
     * @var string|null
     */
    private $reportUri;

    /**
     * XssProtectionMiddleware constructor.
     *
     * @param bool|null $enableProtection
     * @param bool|null $enableBlockMode
     * @param null|string $reportUri
     * @throws MiddlewareException
     */
    public function __construct(?bool $enableProtection = null, ?bool $enableBlockMode = null,
        ?string $reportUri = null)
    {
        parent::__construct('X-Xss-Protection');
        $this->enableProtection = $enableProtection;
        if ($enableBlockMode) {
            $this->enableBlockMode();
        }
        if ($reportUri) {
            $this->setReportUri($reportUri);
        }
    }

    /**
     * Enables the report mode.
     *
     * @throws MiddlewareException
     */
    public function enableBlockMode():void
    {
        if (!$this->enableProtection) {
            throw new MiddlewareException(
                $this,
                "You can't enable the block mode because the XSS protection is disabled"
            );
        }
        if ($this->reportUri) {
            throw new MiddlewareException(
                $this,
                sprintf(
                    "You can't enable the block mode because the report mode is already enabled (see %s)",
                    'https://developer.mozilla.org/docs/Web/HTTP/Headers/X-XSS-Protection'
                )
            );
        }
        $this->blockMode = true;
    }

    /**
     * Enables the report mode and sets the report URI.
     *
     * @param string $reportUri
     * @throws MiddlewareException
     */
    public function setReportUri(string $reportUri):void
    {
        if (!$this->enableProtection) {
            throw new MiddlewareException(
                $this,
                "You can't set the report URI because the XSS protection is disabled"
            );
        }
        if ($this->blockMode) {
            throw new MiddlewareException(
                $this,
                sprintf(
                    "You can't set the report URI because the block mode is already enabled (see %s)",
                    'https://developer.mozilla.org/docs/Web/HTTP/Headers/X-XSS-Protection'
                )
            );
        }
        $this->reportUri = $reportUri;
    }

    /**
     * @inheritdoc
     * @return string
     */
    public function getHeaderValue():string
    {
        $value = $this->enableProtection ? '1' : '0';
        if ($this->blockMode) {
            $value .= '; mode=block';
        }
        if ($this->reportUri) {
            $value .= '; report='.$this->reportUri;
        }
        return $value;
    }
}


<?php
/**
 * Phossa Project
 *
 * PHP version 5.4
 *
 * @category  Library
 * @package   Phossa\Query
 * @author    Hong Zhang <phossa@126.com>
 * @copyright 2015 phossa.com
 * @license   http://mit-license.org/ MIT License
 * @link      http://www.phossa.com/
 */
/*# declare(strict_types=1); */

namespace Phossa\Query\Clause;

/**
 * OnDupTrait
 *
 * @package Phossa\Query
 * @author  Hong Zhang <phossa@126.com>
 * @see     OnDupInterface
 * @version 1.0.0
 * @since   1.0.0 added
 */
trait OnDupTrait
{
    /**
     * ON DUP
     *
     * @var    array
     * @access protected
     */
    protected $clause_ondup = [];

    /**
     * {@inheritDoc}
     */
    public function onDup(/*# string */ $col, /*# string */ $expr)
    {
        $this->clause_ondup[$col] = $expr;
        return $this;
    }

    /**
     * Build ON DUP
     *
     * @return array
     * @access protected
     */
    protected function buildOnDup()/*# : array */
    {
        $result = [];
        foreach ($this->clause_ondup as $col => $expr) {
            $result[] = $col . ' = ' . $expr;
        }
        return $result;
    }
}


<?php
/**
 * Created by PhpStorm.
 * User: christof
 * Date: 11.11.15
 * Time: 14:22.
 */
namespace MandarinMedien\MMMediaBundle\MediaType;

use MandarinMedien\MMMediaBundle\Model\MediaInterface;

class YoutubeMediaType extends BaseMediaType
{
    const NAME = 'mm.media.type.youtube';

    private $loadedMetaData;

    public static function check($data)
    {
        dump($data);

        if (!($id = self::checkYoutubeLink($data))) {
            return;
        }

        return new self($id);
    }

    public function getMetaData()
    {
        if ($this->loadedMetaData) {
            return $this->loadedMetaData;
        }
        $url = sprintf('http://www.youtube.com/oembed?url=http://www.youtube.com/watch?v=%s&format=json', $this->getReference());
        $data = file_get_contents($url);
        $metadata = json_decode($data, true);

        return $metadata;
    }

    private static function checkYoutubeLink($link)
    {
        if (strlen($link) === 11) {
            return false;
        }
        if (preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user)\/))([^\#\?&\"'>]+)/", $link, $matches)) {
            return $matches[1];
        }

        return false;
    }

    /**
     * @param MediaInterface $media
     * @param array|null     $options
     *
     * @return string
     */
    public function getPreview(MediaInterface $media, array $options = null)
    {
        dump($media->getMediaTypeMetadata());

        return $media->getMediaTypeMetadata()['html'];
    }

    /**
     * get the media name.
     *
     * @return string
     */
    public function getMediaName()
    {
        $this->getMetaData()['title'];
    }
}