<?php
/*
 * This file is part of the ReCaptcha Library.
 *
 * (c) Ilya Pokamestov <dario_swain@yahoo.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
*/

namespace DS\Library\ReCaptcha\Http\Client\Guzzle;

use DS\Library\ReCaptcha\Http\Client\ClientInterface;
use DS\Library\ReCaptcha\Http\Response;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
 * ReCaptcha library, Guzzle client wrapper for Guzzle versions 4.*, 5.* and 6.*.
 *
 * @author Ilya Pokamestov <dario_swain@yahoo.com>
 *
 * Class GuzzleClient
 * @package DS\Library\ReCaptcha\Http\Client\Guzzle
 */
class GuzzleClient implements ClientInterface
{
    const GUZZLE_THREE_CLIENT_CLASS = 'Guzzle\Http\Client';
    const GUZZLE_CLIENT_CLASS = 'GuzzleHttp\Client';

    /** @var string|null */
    protected $guzzleVersion = null;
    /** @var \GuzzleHttp\Client|\Guzzle\Http\Client */
    protected $guzzle;
    /** @var RequestBuilder */
    protected $requestBuilder;

    /**
     * @param \GuzzleHttp\Client|\Guzzle\Http\Client $guzzleClient
     * @throw BadMethodCallException
     */
    public function __construct($guzzleClient = null)
    {
        if (null === $guzzleClient) {
            $guzzleClientClass = self::GUZZLE_CLIENT_CLASS;
            if ($this->checkClassExists(self::GUZZLE_THREE_CLIENT_CLASS, false)) {
                $guzzleClientClass = self::GUZZLE_THREE_CLIENT_CLASS;
            } elseif ($this->checkClassExists(self::GUZZLE_CLIENT_CLASS)) {
                $guzzleClientClass = self::GUZZLE_CLIENT_CLASS;
            }

            $guzzleClient = new $guzzleClientClass();
        }

        $this->guzzle = $guzzleClient;
        $this->requestBuilder = new RequestBuilder($this);
    }

    /**
     * @return \Guzzle\Http\Client|\GuzzleHttp\Client
     */
    public function getGuzzleClient()
    {
        return $this->guzzle;
    }

    /**
     * Check if class available
     *
     * @param string $className
     * @param bool $throwException
     * @throw BadMethodCallException
     * @return bool
     */
    protected function checkClassExists($className, $throwException = true)
    {
        if (class_exists($className)) {
            return true;
        }

        if ($throwException) {
            throw new \BadMethodCallException(
                sprintf('%s not found. Please check your dependencies in composer.json', $className)
            );
        }

        return false;
    }

    /**
     * Set Guzzle client version
     *
     * @param $version string
     */
    public function setVersion($version)
    {
        $this->guzzleVersion = $version;
    }

    /**
     * @param RequestInterface $request
     * @return ResponseInterface
     * @throws \Exception
     */
    public function send(RequestInterface $request)
    {
        $guzzleRequest = $this->requestBuilder->buildGuzzleRequest($request);
        $guzzleResponse = $this->guzzle->send($guzzleRequest);

        if ($this->guzzleVersion === Version::VERSION_THREE) {
            $response = new Response(
                $guzzleResponse->getStatusCode(),
                $guzzleResponse->getHeaders()->toArray(),
                $guzzleResponse->getBody(true)
            );
        } else {
            $response = new Response(
                $guzzleResponse->getStatusCode(),
                $guzzleResponse->getHeaders(),
                $guzzleResponse->getBody()->getContents()
            );
        }

        return $response;
    }
}


<?php

/*  threadsafeclient.php
    ~~~~~~~~~
    This module implements the ThreadSafeClient and ThreadSafeArray
    classes. Note that ThreadSafeClient should not be used directly.
    Use the PubControlClient class instead.
    :copyright: (c) 2015 by Fanout, Inc.
    :license: MIT, see LICENSE for more details. */

/* NOTE: The ThreadSafeClient class cannot be used directly.
   Use the PubControlClient class instead. */

namespace PubControl;

// The ThreadSafeClient internal class is used to facilitate async publishing
// via the PHP pthreads feature. It essentially provides the same functionality
// that PubControlClient does along with async-capabilities.
class ThreadSafeClient extends \Thread
{
    public $uri = null;
    public $mutex = null;
    public $is_thread_running = false;
    public $thread_cond = null;
    public $thread_mutex = null;
    public $req_queue = null;
    public $auth_basic_user = null;
    public $auth_basic_pass = null;
    public $auth_jwt_claim = null;
    public $auth_jwt_key = null;
    public $pcc_utilities = null;

    // Initialize with a URI and request queue instance.
    public function __construct($uri, $req_queue)
    {
        $this->req_queue = $req_queue;
        $this->uri = $uri;
        $this->mutex = \Mutex::create();
        $this->pcc_utilities = new PccUtilities();
    }

    // Call this method and pass a username and password to use basic
    // authentication with the configured endpoint.
    function set_auth_basic($username, $password)
    {
        \Mutex::lock($this->mutex);
        $this->auth_basic_user = $username;
        $this->auth_basic_pass = $password;
        \Mutex::unlock($this->mutex);
    }

    // Call this method and pass a claim and key to use JWT authentication
    // with the configured endpoint.
    public function set_auth_jwt($claim, $key)
    {
        \Mutex::lock($this->mutex);
        $this->auth_jwt_claim = $claim;
        $this->auth_jwt_key = $key;
        \Mutex::unlock($this->mutex);
    }

    // The asynchronous publish method for publishing the specified item to the
    // specified channel on the configured endpoint. The callback method is
    // optional and will be passed the publishing results after publishing is
    // complete.
    public function publish_async($channel, $item, $callback=null)
    {
        $export = $item->export();
        $export['channel'] = $channel;
        $uri = null;
        $auth = null;
        \Mutex::lock($this->mutex);
        $uri = $this->uri;
        $auth = $this->pcc_utilities->gen_auth_header($this->auth_jwt_claim,
                $this->auth_jwt_key, $this->auth_basic_user,
                $this->auth_basic_pass);
        $this->ensure_thread();
        \Mutex::unlock($this->mutex);
        $this->queue_req(array('pub', $uri, $auth, $export, $callback));
    }

    // The finish method is a blocking method that ensures that all asynchronous
    // publishing is complete prior to returning and allowing the consumer to
    // proceed.
    public function finish()
    {
        \Mutex::lock($this->mutex);
        if ($this->is_thread_running)
        {
            $this->queue_req(array('stop'));
            $this->join();
            $this->is_thread_running = false;
        }
        \Mutex::unlock($this->mutex);
   }

    // An internal method that is meant to run as a separate thread and process
    // asynchronous publishing requests. The method runs continously and
    // publishes requests in batches containing a maximum of 10 requests. The
    // method completes and the thread is terminated only when a 'stop' command
    // is provided in the request queue.
    public function run()
    {
        $quit = false;
        while (!$quit)
        {
            \Mutex::lock($this->thread_mutex);
            if (count($this->req_queue) == 0)
            {
                \Cond::wait($this->thread_cond, $this->thread_mutex);
                if (count($this->req_queue) == 0)
                {
                    \Mutex::unlock($this->thread_mutex);
                    continue;
                }
            }
            $reqs = array();
            while (count($this->req_queue) > 0 and count($reqs) < 10)
            {
                $m = $this->req_queue->shift();
                if ($m[0] == 'stop')
                {
                    $quit = true;
                    break;
                }
                $reqs[] = array($m[1], $m[2], $m[3], $m[4]);
            }
            \Mutex::unlock($this->thread_mutex);
            if (count($reqs) > 0)
                $this->pubbatch($reqs);
        }
    }

    // An internal method that ensures that asynchronous publish calls are
    // properly processed. This method initializes the required class fields,
    // starts the pubworker worker thread, and is meant to execute only when
    // the consumer makes an asynchronous publish call.
    public function ensure_thread()
    {
        if (!$this->is_thread_running)
        {
            $this->is_thread_running = true;
            $this->thread_cond = \Cond::create();
            $this->thread_mutex = \Mutex::create();
            $this->start();
        }
    }

    // An internal method for adding an asynchronous publish request to the
    // publishing queue. This method will also activate the pubworker worker
    // thread to make sure that it process any and all requests added to
    // the queue.
    public function queue_req($req)
    {
        \Mutex::lock($this->thread_mutex);
        $this->req_queue[] = $req;
        \Cond::signal($this->thread_cond);
        \Mutex::unlock($this->thread_mutex);
    }

    // An internal method for publishing a batch of requests. The requests are
    // parsed for the URI, authorization header, and each request is published
    // to the endpoint. After all publishing is complete, each callback
    // corresponding to each request is called (if a callback was originally
    // provided for that request) and passed a result indicating whether that
    // request was successfully published.
    public function pubbatch($reqs)
    {
        if (count($reqs) == 0)
            throw new \RuntimeException('reqs length == 0');
        $uri = $reqs[0][0];
        $auth_header = $reqs[0][1];
        $items = array();
        $callbacks = array();
        foreach ($reqs as $req)
        {
            $items[] = $req[2];
            $callbacks[] = $req[3];
        }
        $result = null;
        try
        {
            $this->pcc_utilities->pubcall($uri, $auth_header, $items);
            $result = array(true, '');
        }
        catch (\RuntimeException $exception)
        {
            $result = array(false, $exception->getMessage());
        }
        foreach ($callbacks as $callback)
            if (!is_null($callback))
            {
                call_user_func($callback, $result[0], $result[1]);
            }
    }
}

// A thread safe array used for the request queue.
class ThreadSafeArray extends \Stackable
{

    // Required stackable interface method.
    public function run()
    {
    }
}
?>


<?php

namespace Halfpastfour\Collection\Iterator;

use Halfpastfour\Collection\Collection\ArrayAccess;

/**
 * Class Iterator
 * @package Halfpastfour\Collection\Collection
 */
class ArrayAccessIterator implements \Iterator, \Countable
{
	/**
	 * @var ArrayAccess
	 */
	protected $collection;

	/**
	 * The current internal cursor position.
	 *
	 * @var int
	 */
	protected $cursor = 0;

	/**
	 * Iterator constructor.
	 *
	 * @param ArrayAccess $collection
	 *
	 * @internal param array $data
	 */
	public function __construct( ArrayAccess $collection )
	{
		$this->collection = $collection;
	}

	/**
	 * The calculated key map.
	 *
	 * @var array
	 */
	protected $keyMap = [];

	/**
	 * Get the internal cursor.
	 *
	 * @return int
	 */
	public function getCursor()
	{
		return $this->cursor;
	}

	/**
	 * Calculates the keymap for the collection.
	 *
	 * @return $this
	 */
	protected function calculateKeyMap()
	{
		$this->keyMap = array_keys( $this->collection->getArrayCopy() );

		return $this;
	}

	/**
	 * Returns the calculated keymap for the collection.
	 *
	 * @return array
	 */
	public function getKeyMap()
	{
		$this->calculateKeyMap();

		return $this->keyMap;
	}

	/**
	 * Returns key by given cursor position.
	 *
	 * @param int $cursor The cursor position to check.
	 *
	 * @return mixed
	 */
	public function getKey( $cursor )
	{
		$this->calculateKeyMap();
		if( !array_key_exists( $cursor, $this->keyMap ) ) {
			return null;
		}

		return $this->keyMap[ $cursor ];
	}

	/**
	 * Return the value of the current internal cursor position.
	 *
	 * @return mixed
	 */
	public function current()
	{
		return $this->collection->offsetGet( $this->getKey( $this->getCursor() ) );
	}

	/**
	 * Decrease the internal cursor by one.
	 */
	public function previous()
	{
		$this->cursor--;
	}

	/**
	 * Increase the internal cursor by one.
	 */
	public function next()
	{
		$this->cursor++;
	}

	/**
	 * Return the current key according to the internal cursor position.
	 *
	 * @return string|int|bool
	 */
	public function key()
	{
		return $this->getKey( $this->getCursor() );
	}

	/**
	 * Test if the current internal cursor position is valid.
	 *
	 * @return bool
	 */
	public function valid()
	{
		return !is_null( $this->key() );
	}

	/**
	 * Set the internal cursor to the first value in the array of data.
	 *
	 * @return mixed
	 */
	public function rewind()
	{
		$this->cursor = 0;
		$data         = $this->collection->getArrayCopy();
		reset( $data );
		$this->collection->exchangeArray( $data );

		return $this->current();
	}

	/**
	 * @return int
	 */
	public function count()
	{
		return $this->collection->count();
	}
}


<?php

/*  item.php
    ~~~~~~~~~
    This module implements the Item class.
    :authors: Konstantin Bokarius.
    :copyright: (c) 2015 by Fanout, Inc.
    :license: MIT, see LICENSE for more details. */

namespace PubControl;

// The Item class is a container used to contain one or more format
// implementation instances where each implementation instance is of a
// different type of format. An Item instance may not contain multiple
// implementations of the same type of format. An Item instance is then
// serialized into a hash that is used for publishing to clients.
class Item
{
    private $formats = null;
    private $id = null;
    private $prev_id = null;

    // The initialize method can accept either a single Format implementation
    // instance or an array of Format implementation instances. Optionally
    // specify an ID and/or previous ID to be sent as part of the message
    // published to the client.
    public function __construct($formats, $id=null, $prev_id=null)
    {
        $this->id = $id;
        $this->prev_id = $prev_id;
        if (!is_array($formats))
            $formats = array($formats);
        $this->formats = $formats;
    }

    // The export method serializes all of the formats, ID, and previous ID
    // into a hash that is used for publishing to clients. If more than one
    // instance of the same type of Format implementation was specified then
    // an error will be raised.
    public function export()
    {
        $format_types = array();
        foreach ($this->formats as $format)
        {
            $format_class_name = get_class($format);
            if (in_array($format_class_name, $format_types))
                throw new \RuntimeException('Multiple ' .
                        $format_class_name . ' format classes specified');
            array_push($format_types, $format_class_name);
        }
        $out = array();
        if (!is_null($this->id))
            $out['id'] = $this->id;
        if (!is_null($this->prev_id))
            $out['prev-id'] = $this->prev_id;
        foreach ($this->formats as $format)
            $out[$format->name()] = $format->export();
        return $out;
    }
}

?>


<?php
/**
 * Image Manager
 *
 * @link        https://github.com/ripaclub/imgman
 * @copyright   Copyright (c) 2014, RipaClub
 * @license     http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
 */
namespace ImgMan\Operation\Helper\Options;

use ImgMan\Operation\Exception\BadMethodCallException;
use ImgMan\Operation\Exception\InvalidArgumentException;
use Traversable;
use Zend\Stdlib\AbstractOptions;

/**
 * Trait AbstractOptionTrait
 */
trait AbstractOptionTrait
{
    /**
     * We use the '__' prefix to avoid collisions with properties in
     * user-implementations.
     *
     * @var bool
     */
    protected $__strictMode__ = true;

    /**
     * Constructor
     *
     * @param  array|Traversable|null $options
     */
    public function __construct($options = null)
    {
        if (null !== $options) {
            $this->setFromArray($options);
        }
    }

    /**
     * Set one or more configuration properties
     *
     * @param  array|Traversable|AbstractOptions $options
     * @throws InvalidArgumentException
     * @return AbstractOptions Provides fluent interface
     */
    public function setFromArray($options)
    {

        if ($options instanceof self) {
            $options = $options->toArray();
        }

        if (!is_array($options) && !$options instanceof Traversable) {
            throw new InvalidArgumentException(sprintf(
                'Parameter provided to %s must be an %s, %s or %s',
                __METHOD__,
                'array',
                'Traversable',
                'Zend\Stdlib\AbstractOptions'
            ));
        }

        foreach ($options as $key => $value) {
            $this->__set($key, $value);
        }

        return $this;
    }

    /**
     * Cast to array
     *
     * @return array
     */
    public function toArray()
    {
        $array = [];
        $transform = function ($letters) {
            $letter = array_shift($letters);
            return '_' . strtolower($letter);
        };
        foreach ($this as $key => $value) {
            if ($key === '__strictMode__') {
                continue;
            }
            $normalizedKey = preg_replace_callback('/([A-Z])/', $transform, $key);
            $array[$normalizedKey] = $value;
        }
        return $array;
    }

    /**
     * Set a configuration property
     *
     * @see ParameterObject::__set()
     * @param string $key
     * @param mixed $value
     * @throws BadMethodCallException
     * @return void
     */
    public function __set($key, $value)
    {
        $setter = 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
        if ($this->__strictMode__ && !method_exists($this, $setter)) {
            throw new BadMethodCallException(
                'The option "' . $key . '" does not '
                . 'have a matching ' . $setter . ' setter method '
                . 'which must be defined'
            );
        } elseif (!$this->__strictMode__ && !method_exists($this, $setter)) {
            return;
        }
        $this->{$setter}($value);
    }

    /**
     * Get a configuration property
     *
     * @see ParameterObject::__get()
     * @param string $key
     * @throws BadMethodCallException
     * @return mixed
     */
    public function __get($key)
    {
        $getter = 'get' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
        if (!method_exists($this, $getter)) {
            throw new BadMethodCallException(
                'The option "' . $key . '" does not '
                . 'have a matching ' . $getter . ' getter method '
                . 'which must be defined'
            );
        }

        return $this->{$getter}();
    }

    /**
     * Test if a configuration property is null
     * @see ParameterObject::__isset()
     * @param string $key
     * @return bool
     */
    public function __isset($key)
    {
        return null !== $this->__get($key);
    }

    /**
     * Set a configuration property to NULL
     *
     * @see ParameterObject::__unset()
     * @param string $key
     * @throws InvalidArgumentException
     * @return void
     */
    public function __unset($key)
    {
        try {
            $this->__set($key, null);
        } catch (BadMethodCallException $e) {
            throw new InvalidArgumentException(
                'The class property $' . $key . ' cannot be unset as'
                . ' NULL is an invalid value for it',
                0,
                $e
            );
        }
    }

    /**
     * @param boolean $_strictMode__
     */
    public function setStrictMode($_strictMode__)
    {
        $this->__strictMode__ = $_strictMode__;
    }

    /**
     * @return boolean
     */
    public function getStrictMode()
    {
        return $this->__strictMode__;
    }
}


<?php

/*  pccutilities.php
    ~~~~~~~~~
    This module implements the PccUtilities class.
    :authors: Konstantin Bokarius.
    :copyright: (c) 2015 by Fanout, Inc.
    :license: MIT, see LICENSE for more details. */

namespace PubControl;

// The PccUtilities class is an internal class that provides helper methods
// used by both the PubControlClient and ThreadSafeClient classes.
class PccUtilities
{
    // An internal method for preparing the HTTP POST request for publishing
    // data to the endpoint. This method accepts the URI endpoint, authorization
    // header, and a list of items to publish.
    public function pubcall($uri, $auth_header, $items)
    {
        $uri .= '/publish/';
        $content = array();
        $content['items'] = $items;
        $headers = array('Content-Type: application/json');
        if (!is_null($auth_header))
            $headers[] = 'Authorization: ' . $auth_header;
        $results = $this->make_http_request($uri, $headers, $content);
        $this->verify_http_status_code($results[0], $results[1]);
    }

    // An internal method for making an HTTP request to publish a
    // message with the specified URI, headers, and content.
    public function make_http_request($uri, $headers, $content)
    {
        $post = curl_init($uri);
        curl_setopt_array($post, array(
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_POSTFIELDS => json_encode($content)
        ));
        $response = curl_exec($post);
        if (curl_error($post) != '')
            throw new \RuntimeException('Failed to publish: ' .
                    curl_error($post));
        return array($response,
                intval(curl_getinfo($post, CURLINFO_HTTP_CODE)));
    }

    // An internal method used for verifying an HTTP status code where
    // an exception code is thrown if the code is not successful.
    public function verify_http_status_code($response, $http_code)
    {
        if ($http_code < 200 || $http_code >= 300)
            throw new \RuntimeException('Failed to publish: ' . $response);
    }

    // An internal method used to generate an authorization header. The
    // authorization header is generated based on whether basic or JWT
    // authorization information was provided via the publicly accessible
    // 'set_*_auth' methods defined above.
    public function gen_auth_header($auth_jwt_claim, $auth_jwt_key,
            $auth_basic_user, $auth_basic_pass)
    {
        if (!is_null($auth_basic_user))
            return 'Basic ' . base64_encode(
                    "{$auth_basic_user}:{$auth_basic_pass}");
        elseif (!is_null($auth_jwt_claim))
        {
            $claim = $auth_jwt_claim;
            if (!array_key_exists('exp', $claim))
                $claim['exp'] = time() + 3600;

            // Signed with HS256 by default
            return 'Bearer ' . \Firebase\JWT\JWT::encode($claim, $auth_jwt_key);
        }
        else
            return null;
    }
}
?>


<?php

/*  pubcontrolclient.php
    ~~~~~~~~~
    This module implements the PubControlClient class.
    :authors: Konstantin Bokarius.
    :copyright: (c) 2015 by Fanout, Inc.
    :license: MIT, see LICENSE for more details. */

namespace PubControl;

if (class_exists('Thread'))
    include dirname(__FILE__) . '/threadsafeclient.php';

include dirname(__FILE__) . '/pccutilities.php';

// The PubControlClient class allows consumers to publish either synchronously
// or asynchronously to an endpoint of their choice. The consumer wraps a Format
// class instance in an Item class instance and passes that to the publish
// methods. The async publish method has an optional callback parameter that
// is called after the publishing is complete to notify the consumer of the
// result.
class PubControlClient
{
    public $uri = null;
    public $req_queue = null;
    public $tsclient = null;
    public $auth_basic_user = null;
    public $auth_basic_pass = null;
    public $auth_jwt_claim = null;
    public $auth_jwt_key = null;
    public $pcc_utilities = null;

    // Initialize this class with a URL representing the publishing endpoint.
    // If async publishing is supported (i.e., pthread is installed) then
    // instantiate an instance of the ThreadSafeClient.
    public function __construct($uri)
    {
        $this->uri = $uri;
        $this->pcc_utilities = new PccUtilities();
        if ($this->is_async_supported())
        {
            $this->req_queue = new ThreadSafeArray();
            $this->tsclient = new ThreadSafeClient($this->uri,
                    $this->req_queue);
        }
    }

    // Destroy this instance by cleaning up all thread related objects.
    public function __destruct()
    {
        if (!is_null($this->tsclient))
        {
            \Mutex::destroy($this->tsclient->mutex);
            if (!is_null($this->tsclient->thread_mutex))
                \Mutex::destroy($this->tsclient->thread_mutex);
            if (!is_null($this->tsclient->thread_cond))
                \Cond::destroy($this->tsclient->thread_cond);
        }
    }

    // Call this method and pass a username and password to use basic
    // authentication with the configured endpoint.
    function set_auth_basic($username, $password)
    {
        $this->auth_basic_user = $username;
        $this->auth_basic_pass = $password;
        if ($this->tsclient != null)
            $this->tsclient->set_auth_basic($username, $password);
    }

    // Call this method and pass a claim and key to use JWT authentication
    // with the configured endpoint.
    public function set_auth_jwt($claim, $key)
    {
        $this->auth_jwt_claim = $claim;
        $this->auth_jwt_key = $key;
        if ($this->tsclient != null)
            $this->tsclient->set_auth_jwt($claim, $key);
    }

    // The synchronous publish method for publishing the specified item to the
    // specified channel on the configured endpoint.
    public function publish($channel, $item)
    {
        $export = $item->export();
        $export['channel'] = $channel;
        $uri = null;
        $auth = null;
        $uri = $this->uri;
        $auth = $this->pcc_utilities->gen_auth_header($this->auth_jwt_claim,
                $this->auth_jwt_key, $this->auth_basic_user,
                $this->auth_basic_pass);
        $this->pcc_utilities->pubcall($uri, $auth, array($export));
    }

    // The asynchronous publish method for publishing the specified item to the
    // specified channel on the configured endpoint. The callback method is
    // optional and will be passed the publishing results after publishing is
    // complete.
    public function publish_async($channel, $item, $callback=null)
    {
        if (!$this->is_async_supported())
            throw new \RuntimeException('Asynchronous publishing not supported. '
                    . 'Recompile PHP with --enable-maintainer-zts to '
                    . 'turn pthreads on.');
        $this->tsclient->publish_async($channel, $item, $callback);
    }

    // The finish method is a blocking method that ensures that all asynchronous
    // publishing is complete prior to returning and allowing the consumer to
    // proceed.
    public function finish()
    {
        if ($this->tsclient != null)
            $this->tsclient->finish();
    }

    // Determines whether async publishing is supported by checking if the
    // Thread class exists. To turn on async publishing support make sure
    // to compile PHP with pthreads turned on.
    public function is_async_supported()
    {
        if (class_exists('Thread'))
            return true;
        return false;
    }
}
?>


<?php
/**
 * Image Manager
 *
 * @link        https://github.com/ripaclub/imgman
 * @copyright   Copyright (c) 2014, RipaClub
 * @license     http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
 */
namespace ImgMan\Storage\Adapter\Cdn\Amazon\CloudFront;

use Aws\Sdk;
use ImgMan\Storage\Adapter\Cdn\Amazon\ClientManager;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Class ClientAbstractFactory
 */
class CloudFrontServiceAbstractFactory implements AbstractFactoryInterface
{
    /**
     * Config Key
     * @var string
     */
    protected $configKey = 'imgman_amazon_cloud_front_service';

    /**
     * Config
     * @var array
     */
    protected $config;

    /**
     * Determine if we can create a service with name
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @param string $name
     * @param string $requestedName
     * @return boolean
     */
    public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        $config = $this->getConfig($serviceLocator);
        if (empty($config)) {
            return false;
        }

        return (
            isset($config[$requestedName])
            && is_array($config[$requestedName])
            && !empty($config[$requestedName])
            && $serviceLocator->has(ClientManager::class)
            && isset($config[$requestedName]['client'])
            && is_string($config[$requestedName]['client'])
            && $serviceLocator->has(ClientManager::class)
            && $serviceLocator->get(ClientManager::class)->has($config[$requestedName]['client'])
            && isset($config[$requestedName]['domain'])
            && is_string($config[$requestedName]['domain'])
            && !empty($config[$requestedName]['domain'])
            && isset($config[$requestedName]['origin'])
            && is_string($config[$requestedName]['origin'])
            && !empty($config[$requestedName]['origin'])
        );
    }

    /**
     * Create service with name
     *
     * @param ServiceLocatorInterface $serviceLocator
     * @param string $name
     * @param string $requestedName
     * @return CloudFrontService
     */
    public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
    {
        $config = $this->getConfig($serviceLocator)[$requestedName];
        /** @var $sdk Sdk */
        $adapter = new CloudFrontService($serviceLocator->get(ClientManager::class)->get($config['client']));

        $adapter->setOrigin($config['origin']);

        if (isset($config['scheme'])) {
            $adapter->setScheme($config['scheme']);
        }

        return $adapter->setDomain($config['domain']);
    }

    /**
     * Get mongo configuration, if any
     *
     * @param  ServiceLocatorInterface $serviceLocator
     * @return array
     */
    protected function getConfig(ServiceLocatorInterface $serviceLocator)
    {
        if ($this->config !== null) {
            return $this->config;
        }

        if (!$serviceLocator->has('Config')) {
            $this->config = [];
            return $this->config;
        }

        $config = $serviceLocator->get('Config');
        if (!isset($config[$this->configKey])
            || !is_array($config[$this->configKey])
        ) {
            $this->config = [];
            return $this->config;
        }

        $this->config = $config[$this->configKey];
        return $this->config;
    }
}


<?php

namespace Robbie\Psr7;

use Psr\Http\Message\MessageInterface;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;

/**
 * Provides common functionality used between Request and Response objects
 *
 * @package psr7-adapters
 */
abstract class AbstractHttpAdapter
{
    /**
     * @var string
     */
    protected $protocolVersion;

    /**
     * Perform a conversion from a HTTPResponse or HTTPRequest into the corresponding PSR-7 interface
     *
     * @param  HTTPRequest|HTTPResponse $input
     * @return MessageInterface
     */
    abstract public function toPsr7($input);

    /**
     * Perform a conversion from a PSR-7 interface to the corresponding HTTPRequest or HTTPResponse class
     *
     * @param  MessageInterface $input
     * @return HTTPRequest|HTTPResponse
     */
    abstract public function fromPsr7($input);

    /**
     * PSR-7 interfaces support multiple headers per type, whereas SilverStripe classes do not.
     *
     * This method will assign headers as a comma delimited string from the PSR-7 interface to the SilverStripe class
     *
     * @param MessageInterface         $from
     * @param HTTPRequest|HTTPResponse $to
     */
    public function importHeaders(MessageInterface $from, $to)
    {
        foreach ($from->getHeaders() as $key => $headers) {
            foreach ($headers as $header) {
                $to->addHeader($key, $from->getHeaderLine($key));
            }
        }
    }

    /**
     * Get the protocol version - either from a previously set value, or from the server
     *
     * @return string E.g. "1.1"
     */
    public function getProtocolVersion()
    {
        if ($this->protocolVersion) {
            return $this->protocolVersion;
        }

        $protocolAndVersion = $_SERVER['SERVER_PROTOCOL'];
        list($protocol, $version) = explode('/', $protocolAndVersion);
        return $version;
    }

    /**
     * Set the protocol version
     *
     * @param  string $version
     * @return $this
     */
    public function setProtocolVersion($version = '1.1')
    {
        $this->protocolVersion = $version;
        return $this;
    }
}


<?php

/*
 * Copyright (c) 2017 Salah Alkhwlani <yemenifree@yandex.com>
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Yemenifree\Validation\Traits;

use Rakit\Validation\Validation;
use Rakit\Validation\Validator;
use Yemenifree\Validation\TranslateLoader;

trait HasValidator
{
    /** @var array */
    protected $aliases = [];
    /** @var string */
    protected $validatorLocal = 'ar';

    /** @var Validator */
    protected $validator;
    /** @var TranslateLoader */
    protected $translateLoader;

    /** @var Validation */
    protected $validation;

    /**
     * valid data.
     *
     * @param array $data
     * @param array $rules
     * @param array $messages
     * @param array $aliases
     *
     * @return mixed|\Rakit\Validation\Validation
     */
    protected function valid(array $data, array $rules, array $messages = [], array $aliases = [])
    {
        // load translate.
        $this->loadTranslate();

        $this->validation = $this->getValidator()->make($data, $rules, $messages);
        if (\count($aliases) > 0) {
            $this->setAliases($aliases);
        }
        $this->validation->setAliases($this->getAliases());
        $this->validation->validate();

        // if has custom invalid callback.
        if (\method_exists($this, 'InValidCallback') && $this->getValidation()->fails()) {
            return $this->InValidCallback($this->getValidation()->errors()->firstOfAll());
        }

        return !$this->getValidation()->fails();
    }

    /**
     *  load translate.
     */
    protected function loadTranslate(): self
    {
        $this->getValidator()->setMessages($this->getTranslateLoader()->load($this->getValidatorLocal()));

        return $this;
    }

    /**
     * @return Validator
     */
    protected function getValidator(): Validator
    {
        return $this->validator ?: $this->validator = new Validator();
    }

    /**
     * @return TranslateLoader
     */
    public function getTranslateLoader(): TranslateLoader
    {
        return $this->translateLoader ?: $this->translateLoader = new TranslateLoader();
    }

    /**
     * @return string
     */
    public function getValidatorLocal(): string
    {
        return $this->validatorLocal;
    }

    /**
     * set local of validation errors message.
     *
     * @param string $local
     * @param null|string $path
     *
     * @return HasValidator
     */
    public function setValidatorLocal($local, $path = null): self
    {
        $this->validatorLocal = $local;

        if (!empty($path)) {
            $this->getTranslateLoader()->setPath($path);
        }

        return $this;
    }

    /**
     * @return array
     */
    public function getAliases(): array
    {
        return $this->aliases;
    }

    /**
     * @param array $aliases
     *
     * @return self
     */
    public function setAliases($aliases): self
    {
        $this->aliases = $aliases;

        return $this;
    }

    /**
     * @return Validation
     */
    protected function getValidation(): Validation
    {
        return $this->validation;
    }

    /**
     * Get validation errors.
     *
     * @param bool $firstOfAll
     *
     * @return array|\Rakit\Validation\ErrorBag
     */
    protected function getValidErrors($firstOfAll = false)
    {
        return $firstOfAll ? $this->getValidation()->errors()->firstOfAll() : $this->getValidation()->errors();
    }
}


<?php
/*
 * This file is part of the ReCaptcha Library.
 *
 * (c) Ilya Pokamestov <dario_swain@yahoo.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
*/

namespace DS\Library\ReCaptcha\Http;

use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\StreamInterface;

/**
 * ReCaptcha library, PSR7 message implementation.
 *
 * @author Ilya Pokamestov <dario_swain@yahoo.com>
 *
 * Class Message
 * @package DS\Library\ReCaptcha\Http
 */
class Message implements MessageInterface
{
    /** @var array Cached HTTP header collection with lowercase key to values */
    protected $headers = array();
    /** @var string */
    protected $protocol = '1.1';
    /** @var StreamInterface */
    protected $stream;

    /** {@inheritdoc} */
    public function getProtocolVersion()
    {
        return $this->protocol;
    }

    /** {@inheritdoc} */
    public function withProtocolVersion($version)
    {
        $this->protocol = $version;

        return $this;
    }

    /** {@inheritdoc} */
    public function getHeaders()
    {
        return $this->headers;
    }

    /** {@inheritdoc} */
    public function hasHeader($header)
    {
        return isset($this->headers[strtolower($header)]);
    }

    /** {@inheritdoc} */
    public function getHeader($header)
    {
        $name = strtolower($header);

        return isset($this->headers[$name]) ? $this->headers[$name] : array();
    }

    /** {@inheritdoc} */
    public function getHeaderLine($header)
    {
        return implode(', ', $this->getHeader($header));
    }

    /** {@inheritdoc} */
    public function withHeader($header, $value)
    {
        $header = trim($header);
        $name = strtolower($header);
        if (!is_array($value)) {
            $this->headers[$name] = array(trim($value));
        } else {
            $this->headers[$name] = array_map('trim', $value);
        }

        return $this;
    }

    /** {@inheritdoc} */
    public function withAddedHeader($header, $value)
    {
        if (!$this->hasHeader($header)) {
            return $this->withHeader($header, $value);
        }
        $this->headers[strtolower($header)][] = $value;

        return $this;
    }

    /** {@inheritdoc} */
    public function withoutHeader($header)
    {
        if ($this->hasHeader($header)) {
            $name = strtolower($header);
            unset($this->headers[$name]);
        }

        return $this;
    }

    /** {@inheritdoc} */
    public function getBody()
    {
        if (!$this->stream) {
            $this->stream = new Stream('');
        }

        return $this->stream;
    }

    /** {@inheritdoc} */
    public function withBody(StreamInterface $body)
    {
        $this->stream = $body;

        return $this;
    }
}


<?php

/*  pcccbhandler.php
    ~~~~~~~~~
    This module implements the PubControlClientCallbackHandler class.
    :authors: Konstantin Bokarius.
    :copyright: (c) 2015 by Fanout, Inc.
    :license: MIT, see LICENSE for more details. */

namespace PubControl;

// The PubControlClientCallbackHandler class is used internally for allowing
// an async publish call made from the PubControl class to execute a callback
// method only a single time. A PubControl instance can potentially contain
// many PubControlClient instances in which case this class tracks the number
// of successful publishes relative to the total number of PubControlClient
// instances. A failure to publish in any of the PubControlClient instances
// will result in a failed result passed to the callback method and the error
// from the first encountered failure.
class PubControlClientCallbackHandler extends \Stackable
{
    public $completed = null;
    private $callback = null;
    private $num_calls = null;
    private $success = null;
    private $first_error_message = null;

    // Required stackable interface method.
    public function run()
    {
    }

    // The initialize method accepts: a num_calls parameter which is an integer
    // representing the number of PubControlClient instances, and a callback
    // method to be executed after all publishing is complete.
    public function __construct($num_calls, $callback)
    {
        $this->update($num_calls, $callback);
    }

    // Reset the completed and success flags in this instance and update
    // it with the specified num_calls and callback values.
    public function update($num_calls, $callback)
    {
        $this->completed = false;
        $this->num_calls = $num_calls;
        $this->callback = $callback;
        $this->success = true;
    }

    // The handler method which is executed by PubControlClient when publishing
    // is complete. This method tracks the number of publishes performed and
    // when all publishes are complete it will call the callback method
    // originally specified by the consumer. If publishing failures are
    // encountered only the first error is saved and reported to the callback
    // method.
    public function handler($success, $message)
    {
        if (!$success && $this->success)
        {
            $this->success = false;
            $this->first_error_message = $message;
        }
        $this->num_calls -= 1;
        if ($this->num_calls <= 0)
        {
            $this->completed = true;
            $cb = $this->callback;
            call_user_func($cb, $this->success, $this->first_error_message);
        }
    }
}
?>


<?php

namespace Robbie\Psr7;

use GuzzleHttp\Psr7\Response;
use SilverStripe\Control\HTTPResponse;

/**
 * @package psr7-adapters
 */
class HttpResponseAdapter extends AbstractHttpAdapter
{
    /**
     * {@inheritDoc}
     */
    public function toPsr7($input)
    {
        return new Response(
            $input->getStatusCode(),
            $input->getHeaders(),
            $input->getBody(),
            $this->getProtocolVersion(),
            $input->getStatusDescription()
        );
    }

    /**
     * {@inheritDoc}
     */
    public function fromPsr7($input)
    {
        $adapted = new HTTPResponse(
            (string) $input->getBody(),
            $input->getStatusCode(),
            $input->getReasonPhrase()
        );

        $this->importHeaders($input, $adapted);

        return $adapted;
    }
}


<?php
/**
 * RecordBeingEdited
 *
 * @package silverstripe-editlock
 * @author shea@silverstripe.com.au
 **/
class RecordBeingEdited extends DataObject implements PermissionProvider
{

    private static $singular_name = "Record Being Edited";
    private static $plural_name = "Records Being Edited";

    private static $db = array(
        'RecordClass' => 'Varchar',
        'RecordID' => 'Int',
    );

    private static $has_one = array(
        'Editor' => 'Member'
    );

    /**
     * Generates the edit lock warning message displayed to the user
     * @return String
     **/
    public function getLockedMessage()
    {
        $editor = $this->Editor();
        $editorString = $editor->getTitle();
        if ($editor->Email) {
            $editorString .= " <Email'>$editor->Email>";
        }
        $message = sprintf(
            _t('RecordBeingEdited.LOCKEDMESSAGE', 'Sorry, this %s is currently being edited by %s. To avoid conflicts and data loss, editing will be locked until they are finished.'),
            FormField::name_to_label($this->RecordClass),
            $editorString
        );

        if ($this->canEditAnyway()) {
            $editAnywayLink = Controller::join_links(Controller::curr()->getRequest()->requestVar('url'), '?editanyway=1');
            $message .= "";
            $message .= sprintf(_t('RecordBeingEdited.EDITANYWAY', 'I understand the risks, %s edit anyway %s'), "", "");
            $message .= "";
        }

        return $message;
    }

    /**
     * Checks to see if the current user can and edit the record anyway
     * @return Boolean
     **/
    public function canEditAnyway()
    {
        return Permission::check('RECORDBEINGEDITED_EDITANYWAY') ? true : false;
    }

    /**
     * Checks to see if the current user can and has elected to edit the record anyway
     * @return Boolaen
     **/
    public function isEditingAnyway()
    {
        if (!$this->canEditAnyway()) {
            return false;
        }

        $sessionVar = 'EditAnyway_' . Member::currentUserID() . '_' . $this->ID;
        if (Controller::curr()->getRequest()->getVar('editanyway') == '1') {
            Session::set($sessionVar, true);
            return true;
        }
        return Session::get($sessionVar) ? true : false;
    }

    /**
     * @return Arary
     **/
    public function providePermissions()
    {
        return array(
            'RECORDBEINGEDITED_EDITANYWAY' => array(
                'name' => _t('RecordBeingEdited.PERMISSION_EDITANYWAY_DESCRIPTION', 'Edit a record that another user is editing'),
                'help' => _t('RecordBeingEdited.PERMISSION_EDITANYWAY_HELP',  'Let\'s the user dismiss the edit lock and warning'),
                'category' => _t('RecordBeingEdited.PERMISSION_EDITANYWAY_CATEGORY', 'Content permissions'),
                'sort' => 100
            )
        );
    }
}


<?php

namespace Halfpastfour\Collection\Collection;

use Halfpastfour\Collection\Collection;
use Halfpastfour\Collection\Iterator\ArrayAccessIterator;

/**
 * Class ArrayAccess
 * @package Halfpastfour\Collection\Collection
 */
class ArrayAccess extends Collection implements \ArrayAccess, \Countable, ArrayAccessInterface
{
	/**
	 * Check if the given offset exists in the set of data.
	 *
	 * @param mixed $offset The offset to check.
	 *
	 * @return bool
	 */
	public function offsetExists( $offset )
	{
		// Can not retrieve a key based on a value other than a string, integer or boolean
		if( !is_string( $offset ) && !is_int( $offset ) && !is_bool( $offset ) ) {
			return false;
		}

		return array_key_exists( $offset, $this->data );
	}

	/**
	 * Get a value from the given offset.
	 *
	 * @param mixed $offset The offset to get the value from.
	 *
	 * @return mixed
	 */
	public function offsetGet( $offset )
	{
		if( $this->offsetExists( $offset ) ) {
			return $this->data[ $offset ];
		}

		return null;
	}

	/**
	 * Set a value at the given offset.
	 *
	 * @param mixed $offset The offset to set the value at.
	 * @param mixed $value  The value to set.
	 *
	 * @return $this
	 */
	public function offsetSet( $offset, $value )
	{
		$this->data[ $offset ] = $value;

		return $this;
	}

	/**
	 * Unset a value at the given offset. Does nothing if the offset is not found.
	 *
	 * @param mixed $offset The offset to unset the value from.
	 *
	 * @return $this
	 */
	public function offsetUnset( $offset )
	{
		if( $this->offsetExists( $offset ) ) {
			unset( $this->data[ $offset ] );
		}

		return $this;
	}

	/**
	 * Provide a callback to use for sorting the data.
	 *
	 * @param \Closure $callback The callback to be used.
	 *
	 * @return $this
	 */
	public function usort( \Closure $callback )
	{
		usort( $this->data, $callback );
		reset( $this->data );

		return $this;
	}

	/**
	 * Sort the data by key.
	 *
	 * @param int $sortFlags Optional flags to provide to ksort.
	 *
	 * @return $this
	 */
	public function ksort( $sortFlags = null )
	{
		ksort( $this->data, $sortFlags );

		return $this;
	}

	/**
	 * Count the rows of data the collection contains.
	 *
	 * @return int
	 */
	public function count()
	{
		return count( $this->data );
	}

	/**
	 * @return ArrayAccessIterator
	 */
	public function getIterator()
	{
		return new ArrayAccessIterator( $this );
	}
}


<?php

namespace Dakalab\Birthday;

class Birthday
{
    const MAX_AGE = 200; // max age, seems nobody will live so long

    const SUPPORTED_LANGS = ['de', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'nl', 'pt', 'ru', 'th', 'zh', 'zh-TW'];

    protected $birthday;

    protected $lang;

    protected $age;

    protected $constellation;

    /**
     * Constructor
     *
     * @param  string                      $birthday
     * @param  string                      $lang
     * @throws \InvalidArgumentException
     * @throws \OutOfRangeException
     */
    public function __construct($birthday, $lang = 'en')
    {
        $this->birthday = $birthday;
        $this->setLang($lang);
        $this->parse();
    }

    /**
     * Parse the birthday
     *
     * @throws \InvalidArgumentException
     * @throws \OutOfRangeException
     */
    protected function parse(): void
    {
        list('year' => $year, 'month' => $month, 'day' => $day) = self::validate($this->birthday);
        $this->birthday = sprintf('%d-%02d-%02d', $year, $month, $day); // normalize the date
        $this->age = self::calculateAge($year, $month, $day);
        $this->constellation = self::parseConstellation($month, $day);
    }

    /**
     * Get age
     *
     * @return int
     */
    public function getAge(): int
    {
        return $this->age;
    }

    /**
     * Get constellation
     *
     * @return string
     */
    public function getConstellation(): string
    {
        return $this->translate($this->constellation, $this->lang);
    }

    /**
     * Set the language
     *
     * @param  string $lang
     * @return void
     */
    public function setLang($lang): void
    {
        $this->lang = $lang;
    }

    /**
     * Return the birthday in given format
     *
     * @param  string   $format
     * @return string
     */
    public function format($format = null): string
    {
        if (empty($format)) {
            return $this->birthday;
        }

        return date($format, strtotime($this->birthday));
    }

    /**
     * Validate birthday, if it is valid then return the birth year, month and day
     *
     * @param  string                      $birthday
     * @throws \InvalidArgumentException
     * @throws \OutOfRangeException
     * @return array
     */
    public static function validate($birthday): array
    {
        $date = strtotime($birthday);

        if ($date === false) {
            throw new \InvalidArgumentException("Invalid birthday: $birthday");
        }

        $year = date('Y', $date);
        $month = date('n', $date);
        $day = date('j', $date);
        $currentYear = date('Y');

        if ($year > $currentYear || $year <= $currentYear - self::MAX_AGE) {
            throw new \OutOfRangeException('The age is out of range [0, 200)');
        }

        return ['year' => $year, 'month' => $month, 'day' => $day];
    }

    /**
     * Calculate age
     *
     * @param  int   $year
     * @param  int   $month
     * @param  int   $day
     * @return int
     */
    public static function calculateAge($year, $month, $day): int
    {
        $currentYear = date('Y');
        $currentMonth = date('n');
        $currentDay = date('j');
        $age = $currentYear - $year;
        if ($currentMonth < $month || ($currentMonth == $month && $currentDay < $day)) {
            $age--;
        }
        if ($age < 0) {
            $age = 0;
        }

        return $age;
    }

    /**
     * Parse constellation by the given month and day
     *
     * @param  int                         $month
     * @param  int                         $day
     * @throws \InvalidArgumentException
     * @return string
     */
    public static function parseConstellation($month, $day): string
    {
        switch ($month) {
            case 1:
                return $day >= 20 ? 'Aquarius' : 'Capricorn';
            case 2:
                return $day >= 19 ? 'Pisces' : 'Aquarius';
            case 3:
                return $day >= 21 ? 'Aries' : 'Pisces';
            case 4:
                return $day >= 20 ? 'Taurus' : 'Aries';
            case 5:
                return $day >= 21 ? 'Gemini' : 'Taurus';
            case 6:
                return $day >= 22 ? 'Cancer' : 'Gemini';
            case 7:
                return $day >= 23 ? 'Leo' : 'Cancer';
            case 8:
                return $day >= 23 ? 'Virgo' : 'Leo';
            case 9:
                return $day >= 23 ? 'Libra' : 'Virgo';
            case 10:
                return $day >= 24 ? 'Scorpio' : 'Libra';
            case 11:
                return $day >= 23 ? 'Sagittarius' : 'Scorpio';
            case 12:
                return $day >= 22 ? 'Capricorn' : 'Sagittarius';
        }
        throw new \InvalidArgumentException("Invalid month and day: $month , $day");
    }

    /**
     * Load translations
     *
     * @param  string  $lang
     * @return array
     */
    protected function loadTranslation($lang = 'en'): array
    {
        if (!in_array($lang, self::SUPPORTED_LANGS)) {
            $lang = 'en';
        }
        $json = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . $lang . '.json');

        return json_decode($json, true);
    }

    /**
     * Translate the constellation
     *
     * @param  string   $constellation
     * @param  string   $lang
     * @return string
     */
    protected function translate($constellation, $lang = 'en'): string
    {
        $arr = $this->loadTranslation($lang);

        return isset($arr[$constellation]) ? $arr[$constellation] : '';
    }

    /**
     * Magic method to return the normalized birthday string
     * http://php.net/manual/en/language.oop5.magic.php#object.tostring
     *
     * @return string
     */
    public function __toString()
    {
        return $this->birthday;
    }
}


<?php

/**
 * Part of the Antares package.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the 3-clause BSD License.
 *
 * This source file is subject to the 3-clause BSD License that is
 * bundled with this package in the LICENSE file.
 *
 * @package    Access Control
 * @version    0.9.0
 * @author     Antares Team
 * @license    BSD License (3-clause)
 * @copyright  (c) 2017, Antares
 * @link       http://antaresproject.io
 */

namespace Antares\Acl\Http\Controllers;

use Illuminate\Support\Fluent;
use Illuminate\Support\Facades\Input;
use Antares\Acl\Processor\Authorization;
use Antares\Acl\Contracts\Command\Synchronizer;
use Antares\Foundation\Http\Controllers\AdminController;
use Antares\Config\Repository;
use Illuminate\Support\Facades\Response;

class AuthorizationController extends AdminController
{

    /**
     * The synchronizer implementation.
     *
     * @var \Antares\Acl\Contracts\Command\Synchronizer
     */
    protected $synchronizer;

    /**
     * Setup a new controller.
     *
     * @param  \Antares\Acl\Processor\Authorization  $processor
     * @param  \Antares\Acl\Contracts\Command\Synchronizer  $synchronizer
     */
    public function __construct(Authorization $processor, Synchronizer $synchronizer)
    {
        $this->processor    = $processor;
        $this->synchronizer = $synchronizer;
        parent::__construct();
    }

    /**
     * Define the middleware.
     *
     * @return void
     */
    protected function setupMiddleware()
    {
        $this->middleware('antares.manage');
        $this->middleware('antares.csrf', ['only' => 'sync']);
    }

    /**
     * Get default resources landing page.
     *
     * @return mixed
     */
    public function edit()
    {
        return $this->processor->edit($this, Input::get('name', 'antares'));
    }

    /**
     * Update ACL metric.
     *
     * @return mixed
     */
    public function update()
    {
        return $this->processor->update($this, Input::all());
    }

    /**
     * Get sync roles action.
     *
     * @param  string  $vendor
     * @param  string|null  $package
     *
     * @return mixed
     */
    public function sync($vendor, $package = null)
    {
        return $this->processor->sync($this, $vendor, $package);
    }

    /**
     * Response when lists ACL page succeed.
     *
     * @param array $data
     * @param Repository $config
     * @return \Illuminate\View\View
     */
    public function indexSucceed(array $data)
    {
        return view('antares/acl::acl.index', $data);
    }

    /**
     * Response when ACL is updated.
     *
     * @return mixed
     */
    public function updateSucceed()
    {
        $this->synchronizer->handle();
        app('antares.memory')->make('component.default')->update();
        $message = trans('antares/acl::response.acls.update');
        return (app('request')->ajax()) ? Response::json(['message' => $message], 200) : $this->redirectWithMessage(handles("antares::acl/index/roles"), $message);
    }

    /**
     * Response when sync roles succeed.
     *
     * @param  \Illuminate\Support\Fluent   $acl
     *
     * @return mixed
     */
    public function syncSucceed(Fluent $acl)
    {
        $message = trans('antares/acl::response.acls.sync-roles', [
            'name' => $acl->get('name'),
        ]);

        return $this->redirectWithMessage(handles("antares::acl/acl?name={$acl->get('name')}"), $message);
    }

    /**
     * Response when acl verification failed.
     *
     * @return mixed
     */
    public function aclVerificationFailed()
    {
        return $this->suspend(404);
    }

}


<?php

/**
 * Part of the Antares package.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the 3-clause BSD License.
 *
 * This source file is subject to the 3-clause BSD License that is
 * bundled with this package in the LICENSE file.
 *
 * @package    Access Control
 * @version    0.9.0
 * @author     Antares Team
 * @license    BSD License (3-clause)
 * @copyright  (c) 2017, Antares
 * @link       http://antaresproject.io
 */

namespace Antares\Acl\Http\Breadcrumb;

use DaveJamesMiller\Breadcrumbs\Facade as Breadcrumbs;
use Illuminate\Database\Eloquent\Model;

class Breadcrumb
{

    /**
     * Init breadcrumbs
     */
    public function onInit()
    {
        Breadcrumbs::register('staff', function($breadcrumbs) {
            $breadcrumbs->push(trans('antares/foundation::title.staff'), handles('antares::acl/index/roles'));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('staff'));
    }

    /**
     * on roles list
     */
    public function onList()
    {
        $this->onInit();
        Breadcrumbs::register('roles-list', function($breadcrumbs) {
            $breadcrumbs->parent('staff');
            $breadcrumbs->push(trans('antares/acl::title.breadcrumbs.groups'), handles('antares::acl/index/roles'));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('roles-list'));
    }

    /**
     * on create or edit role
     *
     * @param Model $model
     */
    public function onRoleCreateOrEdit(Model $model = null)
    {
        $this->onList();
        Breadcrumbs::register('edit-role', function($breadcrumbs) use($model) {
            $breadcrumbs->parent('roles-list');
            $exists = is_null($model) ? false : $model->exists;
            $name   = ($exists) ? 'Edit Group ' . $model->full_name : 'Add Group';
            $breadcrumbs->push($name, '#');
        });
        view()->share('breadcrumbs', Breadcrumbs::render('edit-role'));
    }

    /**
     * On users list
     */
    protected function onUsersList()
    {
        $this->onInit();

        Breadcrumbs::register('users-list', function($breadcrumbs) {
            $breadcrumbs->parent('staff');
            $breadcrumbs->push(trans('antares/acl::title.breadcrumbs.users'), handles('antares::acl/index/users'));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('users-list'));
    }

    /**
     * when shows roles list
     */
    public function onAdminsList()
    {
        $this->onInit();
        Breadcrumbs::register('admins-list', function($breadcrumbs) {
            $breadcrumbs->parent('staff');
            $breadcrumbs->push(trans('antares/acl::title.breadcrumbs.users'), handles('antares::acl/index/users'));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('admins-list'));
    }

    /**
     * on user create or edit
     *
     * @param Model $model
     */
    public function onUserCreateOrEdit(Model $model)
    {
        $this->onUsersList();
        $name = $model->exists ? 'User Edit ' . $model->fullname : 'User Add';
        Breadcrumbs::register('user', function($breadcrumbs) use($name) {
            $breadcrumbs->parent('users-list');
            $breadcrumbs->push($name, '#');
        });
        view()->share('breadcrumbs', Breadcrumbs::render('user'));
    }

    /**
     * On areas list
     */
    public function onAreasList()
    {

        $this->onInit();
        Breadcrumbs::register('areas-list', function($breadcrumbs) {
            $breadcrumbs->parent('staff');
            $breadcrumbs->push(trans('antares/acl::messages.areas'), handles('antares::acl/areas/index'));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('areas-list'));
    }

    /**
     * On area create
     */
    public function onAreaCreate()
    {
        $this->onAreasList();
        Breadcrumbs::register('area-create', function($breadcrumbs) {
            $breadcrumbs->parent('areas-list');
            $breadcrumbs->push(trans('antares/acl::messages.area_add'), '#');
        });
        view()->share('breadcrumbs', Breadcrumbs::render('area-create'));
    }

    /**
     * On area edit
     */
    public function onAreaEdit(Model $model)
    {
        $this->onAreasList();
        Breadcrumbs::register('area-edit', function($breadcrumbs) use($model) {
            $breadcrumbs->parent('areas-list');
            $breadcrumbs->push(trans('antares/acl::messages.area_edit', ['name' => $model->getHumanReadableName()]), '#');
        });
        view()->share('breadcrumbs', Breadcrumbs::render('area-edit'));
    }

    /**
     * On area edit
     */
    public function onAcl(Model $model)
    {
        $this->onList();
        Breadcrumbs::register('edit-acl', function($breadcrumbs) use($model) {
            $breadcrumbs->parent('roles-list');
            $breadcrumbs->push(trans('antares/acl::messages.acl_rules', ['fullname' => $model->full_name]));
        });
        view()->share('breadcrumbs', Breadcrumbs::render('edit-acl'));
    }

}


<?php
/*
 * Copyright (c) Atsuhiro Kubo <kubo@iteman.jp>,
 * All rights reserved.
 *
 * This file is part of PHPMentorsPageflowerBundle.
 *
 * This program and the accompanying materials are made available under
 * the terms of the BSD 2-Clause License which accompanies this
 * distribution, and is available at http://opensource.org/licenses/BSD-2-Clause
 */

namespace PHPMentors\PageflowerBundle\Conversation;

use PHPMentors\PageflowerBundle\Controller\ConversationalControllerInterface;
use PHPMentors\PageflowerBundle\Controller\ReflectionConversationalController;
use PHPMentors\PageflowerBundle\Pageflow\Page;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;

class ConversationContext
{
    /**
     * @var Conversation
     */
    private $conversation;

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

    /**
     * @var ConversationalControllerInterface
     */
    private $conversationalController;

    /**
     * @var ReflectionConversationalController
     */
    private $reflectionConversationalController;

    /**
     * @var RouterInterface
     */
    private $router;

    /**
     * @param string          $conversationParameterName
     * @param RouterInterface $router
     */
    public function __construct($conversationParameterName, RouterInterface $router)
    {
        $this->conversationParameterName = $conversationParameterName;
        $this->router = $router;
    }

    /**
     * @param Conversation $conversation
     */
    public function setConversation($conversation)
    {
        $this->conversation = $conversation;
    }

    /**
     * @return Conversation
     */
    public function getConversation()
    {
        return $this->conversation;
    }

    /**
     * @return string
     */
    public function getConversationParameterName()
    {
        return $this->conversationParameterName;
    }

    /**
     * @param ConversationalControllerInterface $conversationalController
     */
    public function setConversationalController(ConversationalControllerInterface $conversationalController)
    {
        $this->conversationalController = $conversationalController;
    }

    /**
     * @return ConversationalControllerInterface
     */
    public function getConversationalController()
    {
        return $this->conversationalController;
    }

    /**
     * @param ReflectionConversationalController $reflectionConversationalController
     */
    public function setReflectionConversationalController(ReflectionConversationalController $reflectionConversationalController)
    {
        $this->reflectionConversationalController = $reflectionConversationalController;
    }

    /**
     * @return ReflectionConversationalController
     */
    public function getReflectionConversationalController()
    {
        return $this->reflectionConversationalController;
    }

    /**
     * {@inheritdoc}
     */
    public function generateUrl($routeName, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
    {
        if ($this->conversation !== null) {
            $route = $this->router->getRouteCollection()->get($routeName);
            if ($route !== null) {
                $controllerName = $route->getDefault('_controller');
                $controllerServiceId = substr($controllerName, 0, strpos($controllerName, ':'));
                if ($controllerServiceId == $this->conversation->getPageflow()->getPageflowId()) {
                    $parameters[$this->conversationParameterName] = $this->conversation->getConversationId();
                }
            }
        }

        return $this->router->generate($routeName, $parameters, $referenceType);
    }

    /**
     * @return Page
     */
    public function getCurrentPage()
    {
        if ($this->conversation === null) {
            return null;
        } else {
            return $this->conversation->getCurrentPage();
        }
    }

    /**
     * @return Page
     */
    public function getPreviousPage()
    {
        if ($this->conversation === null) {
            return null;
        } else {
            return $this->conversation->getPreviousPage();
        }
    }

    /**
     * @return bool
     *
     * @since Method available since Release 1.1.0
     */
    public function onFirstStep()
    {
        if ($this->conversation === null) {
            return null;
        } else {
            return $this->conversation->onFirstStep();
        }
    }

    /**
     * @return bool
     *
     * @deprecated Deprecated since version 1.1.0, to be removed in 2.0.0
     */
    public function isFirstTime()
    {
        return $this->onFirstStep();
    }
}


<?php

namespace Adback\ApiClient\Driver;

/**
 * Class PdoScriptCache
 */
class PdoScriptCache extends SqlScriptCache implements ScriptCacheInterface
{
    protected $connection;

    /**
     * @param \PDO $connection
     */
    public function __construct(\PDO $connection)
    {
        $this->connection = $connection;
    }

    /**
     * @param string $key
     *
     * @return string|null
     */
    protected function get($key)
    {
        $request = $this->connection->prepare('SELECT our_value FROM adback_cache_table WHERE our_key = :key LIMIT 1');
        $request->execute([
            'key' => $key,
        ]);

        $data = $request->fetch();
        $request->closeCursor();
        if (is_array($data) && array_key_exists('our_value', $data)) {
            return $data['our_value'];
        }

        return null;
    }

    /**
     * @param string $key
     * @param string $value
     */
    protected function set($key, $value)
    {
        $this->clear($key);
        $request = $this->connection->prepare("INSERT INTO adback_cache_table (our_key, our_value) VALUES (:key, :value)");
        $request->execute([
            'key' => $key,
            'value' => $value,
        ]);
    }

    /**
     * @param string $key
     */
    protected function clear($key)
    {
        $request = $this->connection->prepare("DELETE FROM adback_cache_table WHERE our_key = :key");
        $request->execute([
            'key' => $key,
        ]);
    }
}


<?php
/*
 * Copyright (c) Atsuhiro Kubo <kubo@iteman.jp>,
 * All rights reserved.
 *
 * This file is part of PHPMentorsPageflowerBundle.
 *
 * This program and the accompanying materials are made available under
 * the terms of the BSD 2-Clause License which accompanies this
 * distribution, and is available at http://opensource.org/licenses/BSD-2-Clause
 */

namespace PHPMentors\PageflowerBundle\Form\Extension\Conversation\Type;

use PHPMentors\PageflowerBundle\Conversation\ConversationContext;
use PHPMentors\PageflowerBundle\Conversation\ConversationContextAwareInterface;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;

class FormTypeConversationExtension extends AbstractTypeExtension implements ConversationContextAwareInterface
{
    /**
     * @var ConversationContext
     */
    private $conversationContext;

    /**
     * @param ConversationContext $conversationContext
     */
    public function setConversationContext(ConversationContext $conversationContext)
    {
        $this->conversationContext = $conversationContext;
    }

    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $conversation = $this->conversationContext->getConversation();
        if ($conversation !== null) {
            $builder->setAttribute('conversation_factory', $builder->getFormFactory());
        }
    }

    /**
     * {@inheritdoc}
     */
    public function finishView(FormView $view, FormInterface $conversationForm, array $options)
    {
        $conversation = $this->conversationContext->getConversation();
        if ($conversation !== null && !$view->parent && $options['compound']) {
            $conversationForm = $conversationForm->getConfig()->getAttribute('conversation_factory')->createNamed(
                $this->conversationContext->getConversationParameterName(),
                'Symfony\Component\Form\Extension\Core\Type\HiddenType',
                $conversation->getConversationId(),
                array('mapped' => false)
            );

            $conversationFormView = $conversationForm->createView($view);
            $conversationFormView->vars['full_name'] = $this->conversationContext->getConversationParameterName();
            $view->children[$this->conversationContext->getConversationParameterName()] = $conversationFormView;
        }
    }

    /**
     * {@inheritdoc}
     */
    public function getExtendedType()
    {
        return 'Symfony\Component\Form\Extension\Core\Type\FormType';

        return 'form';
    }
}


<?php

/**
 * Part of the Antares package.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the 3-clause BSD License.
 *
 * This source file is subject to the 3-clause BSD License that is
 * bundled with this package in the LICENSE file.
 *
 * @package    Access Control
 * @version    0.9.0
 * @author     Antares Team
 * @license    BSD License (3-clause)
 * @copyright  (c) 2017, Antares
 * @link       http://antaresproject.io
 */

namespace Antares\Acl\Http\Presenters;

use Antares\Contracts\Html\Form\Factory as FormFactory;
use Antares\Contracts\Html\Form\Grid as FormGrid;
use Antares\Acl\Http\Datatables\Administrators;
use Illuminate\Contracts\Auth\Authenticatable;
use Antares\Acl\Http\Breadcrumb\Breadcrumb;
use Antares\Contracts\Html\Form\Fieldset;
use Antares\Contracts\Html\Form\Builder;
use Illuminate\Support\Facades\Event;
use Illuminate\Contracts\Auth\Guard;

class User extends Presenter
{

    /**
     * Current logged in user contract implementation.
     *
     * @var Authenticatable|null
     */
    protected $user;

    /**
     * breadcrumbs instance
     *
     * @var Breadcrumb
     */
    protected $breadcrumb;

    /**
     * Administrators datatable instance
     *
     * @var Administrators
     */
    protected $datatables;

    /**
     * Construct a new User presenter.
     *
     * @param  Guard  $auth
     * @param  FormFactory  $form
     * @param Breadcrumb $breadcrumb
     */
    public function __construct(Guard $auth, FormFactory $form, Breadcrumb $breadcrumb, Administrators $datatables)
    {
        $this->user       = $auth->user();
        $this->form       = $form;
        $this->breadcrumb = $breadcrumb;
        $this->datatables = $datatables;
    }

    /**
     * Table View Generator for Antares\Model\Brands.
     * @return String
     */
    public function table()
    {
        $this->breadcrumb->onInit();
        return $this->datatables->render('antares/acl::users.index');
    }

    /**
     * Form View Generator for Antares\Model\User.
     *
     * @param  User  $model
     *
     * @return Builder
     */
    public function form($model)
    {
        $this->breadcrumb->onUserCreateOrEdit($model);
        return $this->form->of('antares.users', function (FormGrid $form) use ($model) {
                    $form->name('user.form');
                    $form->resource($this, 'antares::acl/index/users', $model);
                    $form->hidden('id');
                    $form->fieldset('User fields', function (Fieldset $fieldset) use($model) {
                        $fieldset->control('input:text', 'email')
                                ->label(trans('antares/foundation::label.users.email'));

                        $fieldset->control('input:text', 'firstname')
                                ->label(trans('antares/foundation::label.users.firstname'));

                        $fieldset->control('input:text', 'lastname')
                                ->label(trans('antares/foundation::label.users.lastname'));

                        $fieldset->control('input:password', 'password')
                                ->label(trans('antares/foundation::label.users.password'));

                        if ($model->id != user()->id) {
                            $status = $fieldset->control('input:checkbox', 'status')
                                    ->label(trans('antares/foundation::label.users.active'))
                                    ->value(1);
                            if ($model->status) {
                                $status->checked();
                            }
                        }

                        $fieldset->control('select', 'roles[]')
                                ->label(trans('antares/foundation::label.users.roles'))
                                ->options(function () {
                                    $roles = app('antares.role');
                                    if (config('antares/acl::allow_register_with_other_roles')) {
                                        return $roles->managers()->pluck('name', 'id');
                                    } else {
                                        return user()->roles->pluck('name', 'id');
                                    }
                                })
                                ->value(function ($row) {
                                    $roles = [];
                                    foreach ($row->roles as $row) {
                                        $roles[] = $row->id;
                                    }
                                    return $roles;
                                });
                        $fieldset->control('button', 'button')
                                ->attributes(['type' => 'submit', 'class' => 'btn btn--md btn--primary mdl-button mdl-js-button mdl-js-ripple-effect'])
                                ->value(trans('antares/foundation::label.save_changes'));

                        $fieldset->control('button', 'cancel')
                                ->field(function() {
                                    return app('html')->link(handles("antares::acl/index/users"), trans('antares/foundation::label.cancel'), ['class' => 'btn btn--md btn--default mdl-button mdl-js-button']);
                                });
                    });
                    $form->rules([
                        'email'     => ['required', 'email', 'unique:tbl_users,email' . ((!$model->exists) ? '' : ',' . $model->id)],
                        'firstname' => ['required'],
                        'lastname'  => ['required'],
                        'roles'     => ['required'],
                    ]);
                });
    }

    /**
     * Fire Event related to eloquent process.
     *
     * @param  string  $type
     * @param  array   $parameters
     *
     * @return void
     */
    protected function fireEvent($type, array $parameters = [])
    {
        Event::fire("antares.{$type}: users", $parameters);
        Event::fire("antares.{$type}: user.account", $parameters);
    }

}


<?php

namespace Adback\ApiClient\Client;

/**
 * Class Client
 */
class Client
{
    /**
     * @param $url
     *
     * @return Response
     */
    public function get($url)
    {
        if (function_exists('curl_version')) {
            $curl = curl_init($url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
            $data = curl_exec($curl);
            curl_close($curl);
        } else {
            $data = @file_get_contents($url);
        }

        $response = new Response($data);

        return $response;
    }
}


<?php

namespace Mamikon\RoleManager\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
use Mamikon\RoleManager\Models\Permissions;
/**
 * Permission request validation
 *
 * @category Laravel_Package
 * @package  Mamikon\RoleManager
 * @author   Mamikon Arakelyan <m.araqelyan@gmail.com>
 * @license  https://github.com/mamikon/role-manager/blob/master/LICENSE.md MIT
 * @link     https://github.com/mamikon/role-manager
 */
class PermissionRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        $return = [
            'description' => 'required|max:255',
            'name' => 'required|max:255|unique:' .
                config('roleManager.permissionsTable') . ',name',
            'class' => 'classExist',
            'method' => 'required_with:class|methodExist'

        ];

        if (Request::isMethod('put')) {
            $permission = Permissions::where(
                'id', Request::route('permission')
            )->firstOrFail();
            if ($permission->name == Request::input('name')) {
                $return['name'] = 'required|max:255';
            }

        }
        return $return;
    }
}


<?php

/**
 * Part of the Antares package.
 *
 * NOTICE OF LICENSE
 *
 * Licensed under the 3-clause BSD License.
 *
 * This source file is subject to the 3-clause BSD License that is
 * bundled with this package in the LICENSE file.
 *
 * @package    Access Control
 * @version    0.9.0
 * @author     Antares Team
 * @license    BSD License (3-clause)
 * @copyright  (c) 2017, Antares
 * @link       http://antaresproject.io
 */

namespace Antares\Acl\Http\Handlers;

use Antares\Foundation\Support\MenuHandler;

class GroupsBreadcrumbMenu extends MenuHandler
{

    /**
     * Menu configuration.
     *
     * @var array
     */
    protected $menu = [
        'id'    => 'roles',
        'title' => 'Groups',
        'link'  => 'antares::acl',
        'icon'  => null,
        'boot'  => [
            'group' => 'menu.top.roles',
            'on'    => 'antares/acl::roles.index'
        ]
    ];

    /**
     * Get the title.
     * @param  string  $value
     * @return string
     */
    public function getTitleAttribute($value)
    {
        return $this->container->make('translator')->trans($value);
    }

    /**
     * Create a handler.
     * @return void
     */
    public function handle()
    {
        $acl           = app('antares.acl')->make('antares/acl');
        $canCreateRole = $acl->can('create-role');
        if (!$canCreateRole) {
            return;
        }
        $this->createMenu();

        if ($canCreateRole) {
            $this->handler
                    ->add('role-add', '^:roles')
                    ->title('Add Group')
                    ->icon('zmdi-plus-circle-o')
                    ->link(handles('antares::acl/index/roles/create'));
        }
    }

}


<?php
/*
 * Copyright (c) Atsuhiro Kubo <kubo@iteman.jp>,
 * All rights reserved.
 *
 * This file is part of PHPMentorsPageflowerBundle.
 *
 * This program and the accompanying materials are made available under
 * the terms of the BSD 2-Clause License which accompanies this
 * distribution, and is available at http://opensource.org/licenses/BSD-2-Clause
 */

namespace PHPMentors\PageflowerBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;

class ReplaceTemplatingGlobalsDefinitionPass implements CompilerPassInterface
{
    /**
     * {@inheritdoc}
     */
    public function process(ContainerBuilder $container)
    {
        if ($container->hasDefinition('templating.globals')) {
            foreach ($container->getDefinition('templating.globals')->getMethodCalls() as $methodCall) {
                list($method, $arguments) = $methodCall;
                $container->getDefinition('phpmentors_pageflower.conversational_global_variables')->addMethodCall($method, $arguments);
            }

            $container->setAlias('templating.globals', 'phpmentors_pageflower.conversational_global_variables');
        }
    }
}


<?php

/*
 * doctrine-base-repositories (https://github.com/juliangut/doctrine-base-repositories).
 * Doctrine2 utility repositories.
 *
 * @license MIT
 * @link https://github.com/juliangut/doctrine-base-repositories
 * @author Julián Gutiérrez <juliangut@gmail.com>
 */

declare(strict_types=1);

namespace Jgut\Doctrine\Repository;

use Doctrine\Common\Util\Inflector;

/**
 * Repository trait.
 *
 * @method mixed find($id, $lockMode = null, $lockVersion = null)
 * @method mixed findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 * @method mixed findOneBy(array $criteria, array $orderBy = null)
 * @method mixed findAll()
 */
trait RepositoryTrait
{
    /**
     * Supported magic methods.
     *
     * @var array
     */
    protected static $supportedMethods = [
        'findBy',
        'findOneBy',
        'findPaginatedBy',
        'removeBy',
        'removeOneBy',
        'countBy',
    ];

    /**
     * Methods that support exception throwing on fail.
     *
     * @var array
     */
    protected static $falibleMethods = [
        'findBy',
        'findOneBy',
        'findPaginatedBy',
    ];

    /**
     * Auto flush changes.
     *
     * @var bool
     */
    protected $autoFlush = false;

    /**
     * New object factory.
     *
     * @var callable
     */
    protected $objectFactory;

    /**
     * Get automatic manager flushing.
     *
     * @return bool
     */
    public function isAutoFlush(): bool
    {
        return $this->autoFlush;
    }

    /**
     * Set automatic manager flushing.
     *
     * @param bool $autoFlush
     */
    public function setAutoFlush(bool $autoFlush = true)
    {
        $this->autoFlush = $autoFlush;
    }

    /**
     * Manager flush.
     */
    public function flush()
    {
        $this->getManager()->flush();
    }

    /**
     * Find elements or throw an exception if none found.
     *
     * @param array      $criteria
     * @param array|null $orderBy
     * @param int|null   $limit
     * @param int|null   $offset
     *
     * @throws FindException
     *
     * @return object[]
     */
    public function findByOrFail(array $criteria, array $orderBy = null, int $limit = null, int $offset = null): array
    {
        $objects = $this->findBy($criteria, $orderBy, $limit, $offset);

        if (\count($objects) === 0) {
            throw new FindException('FindBy did not return any results');
        }

        return $objects;
    }

    /**
     * Find elements or throw an exception if none found.
     *
     * @param array $criteria
     *
     * @throws FindException
     *
     * @return object
     */
    public function findOneByOrFail(array $criteria)
    {
        $object = $this->findOneBy($criteria);

        if ($object === null) {
            throw new FindException('FindOneBy did not return any results');
        }

        return $object;
    }

    /**
     * Find one object by a set of criteria or create a new one.
     *
     * @param array $criteria
     *
     * @throws \RuntimeException
     *
     * @return object
     */
    public function findOneByOrGetNew(array $criteria)
    {
        $object = $this->findOneBy($criteria);

        if ($object === null) {
            $object = $this->getNew();
        }

        return $object;
    }

    /**
     * Get a new managed object instance.
     *
     * @throws \RuntimeException
     *
     * @return object
     */
    public function getNew()
    {
        $object = \call_user_func($this->getObjectFactory());

        if (!$this->canBeManaged($object)) {
            throw new \RuntimeException(
                \sprintf(
                    'Object factory must return an instance of %s. "%s" returned',
                    $this->getClassName(),
                    \is_object($object) ? \get_class($object) : \gettype($object)
                )
            );
        }

        return $object;
    }

    /**
     * Get object factory.
     *
     * @return callable
     */
    private function getObjectFactory(): callable
    {
        if ($this->objectFactory === null) {
            $className = $this->getClassName();

            $this->objectFactory = function () use ($className) {
                return new $className();
            };
        }

        return $this->objectFactory;
    }

    /**
     * Set object factory.
     *
     * @param callable $objectFactory
     */
    public function setObjectFactory(callable $objectFactory)
    {
        $this->objectFactory = $objectFactory;
    }

    /**
     * Add objects.
     *
     * @param object|iterable $objects
     * @param bool            $flush
     *
     * @throws \InvalidArgumentException
     */
    public function add($objects, bool $flush = false)
    {
        $this->runManagerAction('persist', $objects, $flush);
    }

    /**
     * Remove all objects.
     *
     * @param bool $flush
     */
    public function removeAll(bool $flush = false)
    {
        $this->runManagerAction('remove', $this->findAll(), $flush);
    }

    /**
     * Remove object filtered by a set of criteria.
     *
     * @param array $criteria
     * @param bool  $flush
     */
    public function removeBy(array $criteria, bool $flush = false)
    {
        $this->runManagerAction('remove', $this->findBy($criteria), $flush);
    }

    /**
     * Remove first object filtered by a set of criteria.
     *
     * @param array $criteria
     * @param bool  $flush
     */
    public function removeOneBy(array $criteria, bool $flush = false)
    {
        $this->runManagerAction('remove', $this->findOneBy($criteria), $flush);
    }

    /**
     * Remove objects.
     *
     * @param object|iterable|string|int $objects
     * @param bool                       $flush
     *
     * @throws \InvalidArgumentException
     */
    public function remove($objects, bool $flush = false)
    {
        if (!\is_object($objects) && !is_iterable($objects)) {
            $objects = $this->find($objects);
        }

        $this->runManagerAction('remove', $objects, $flush);
    }

    /**
     * Refresh objects.
     *
     * @param object|iterable $objects
     *
     * @throws \InvalidArgumentException
     */
    public function refresh($objects)
    {
        $backupAutoFlush = $this->autoFlush;

        $this->autoFlush = false;
        $this->runManagerAction('refresh', $objects, false);

        $this->autoFlush = $backupAutoFlush;
    }

    /**
     * Detach objects.
     *
     * @param object|iterable $objects
     *
     * @throws \InvalidArgumentException
     */
    public function detach($objects)
    {
        $backupAutoFlush = $this->autoFlush;

        $this->autoFlush = false;
        $this->runManagerAction('detach', $objects, false);

        $this->autoFlush = $backupAutoFlush;
    }

    /**
     * Get all objects count.
     *
     * @return int
     */
    public function countAll(): int
    {
        return $this->countBy([]);
    }

    /**
     * Get object count filtered by a set of criteria.
     *
     * @param mixed $criteria
     *
     * @return int
     */
    abstract public function countBy($criteria): int;

    /**
     * Adds support for magic methods.
     *
     * @param string $method
     * @param array  $arguments
     *
     * @throws \BadMethodCallException
     *
     * @return mixed
     */
    public function __call($method, $arguments)
    {
        if (\count($arguments) === 0) {
            throw new \BadMethodCallException(\sprintf(
                'You need to call %s::%s with a parameter',
                $this->getClassName(),
                $method
            ));
        }

        $baseMethod = $this->getSupportedMethod($method);

        if (\in_array($baseMethod, static::$falibleMethods, true) && \preg_match('/OrFail$/', $method)) {
            $field = \substr($method, \strlen($baseMethod), -6);
            $method = $baseMethod . 'OrFail';
        } elseif ($baseMethod === 'findOneBy' && \preg_match('/OrGetNew$/', $method)) {
            $field = \substr($method, \strlen($baseMethod), -8);
            $method = 'findOneByOrGetNew';
        } else {
            $field = \substr($method, \strlen($baseMethod));
            $method = $baseMethod;
        }

        return $this->callSupportedMethod($method, Inflector::camelize($field), $arguments);
    }

    /**
     * Get supported magic method.
     *
     * @param string $method
     *
     * @throws \BadMethodCallException
     *
     * @return string
     */
    private function getSupportedMethod(string $method): string
    {
        foreach (static::$supportedMethods as $supportedMethod) {
            if (\strpos($method, $supportedMethod) === 0) {
                return $supportedMethod;
            }
        }

        throw new \BadMethodCallException(\sprintf(
            'Undefined method "%s". Method call must start with one of "%s"!',
            $method,
            \implode('", "', static::$supportedMethods)
        ));
    }

    /**
     * Internal method call.
     *
     * @param string $method
     * @param string $fieldName
     * @param array  $arguments
     *
     * @throws \BadMethodCallException
     *
     * @return mixed
     */
    protected function callSupportedMethod(string $method, string $fieldName, array $arguments)
    {
        $classMetadata = $this->getClassMetadata();

        if (!$classMetadata->hasField($fieldName) && !$classMetadata->hasAssociation($fieldName)) {
            throw new \BadMethodCallException(\sprintf(
                'Invalid call to %s::%s. Field "%s" does not exist',
                $this->getClassName(),
                $method,
                $fieldName
            ));
        }

        // @codeCoverageIgnoreStart
        $parameters = \array_merge(
            [$fieldName => $arguments[0]],
            \array_slice($arguments, 1)
        );

        return \call_user_func_array([$this, $method], $parameters);
        // @codeCoverageIgnoreEnd
    }

    /**
     * Run manager action.
     *
     * @param string          $action
     * @param object|iterable $objects
     * @param bool            $flush
     *
     * @throws \InvalidArgumentException
     */
    protected function runManagerAction(string $action, $objects, bool $flush)
    {
        $manager = $this->getManager();

        if (!is_iterable($objects)) {
            $objects = \array_filter([$objects]);
        }

        foreach ($objects as $object) {
            if (!$this->canBeManaged($object)) {
                throw new \InvalidArgumentException(
                    \sprintf(
                        'Managed object must be a %s. "%s" given',
                        $this->getClassName(),
                        \is_object($object) ? \get_class($object) : \gettype($object)
                    )
                );
            }

            $manager->$action($object);
        }

        // @codeCoverageIgnoreStart
        if ($objects instanceof \Traversable) {
            $objects = \iterator_to_array($objects);
        }
        // @codeCoverageIgnoreEnd

        $this->flushObjects($objects, $flush);
    }

    /**
     * Flush managed objects.
     *
     * @param array $objects
     * @param bool  $flush
     */
    protected function flushObjects(array $objects, bool $flush)
    {
        if ($flush || $this->autoFlush) {
            $this->getManager()->flush($objects);
        }
    }

    /**
     * Check if the object is of the proper type.
     *
     * @param object $object
     *
     * @return bool
     */
    protected function canBeManaged($object): bool
    {
        $managedClass = $this->getClassName();

        return $object instanceof $managedClass;
    }

    /**
     * Returns the fully qualified class name of the objects managed by the repository.
     *
     * @return string
     */
    abstract public function getClassName(): string;

    /**
     * Get object manager.
     *
     * @return \Doctrine\Common\Persistence\ObjectManager
     */
    abstract protected function getManager();

    /**
     * Get class metadata.
     *
     * @return \Doctrine\Common\Persistence\Mapping\ClassMetadata
     */
    abstract protected function getClassMetadata();
}