<?php
/**
 * PEAR_Builder for building PHP extensions (PECL packages)
 *
 * PHP versions 4 and 5
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    CVS: $Id: Builder.php 313024 2011-07-06 19:51:24Z dufuz $
 * @link       http://pear.php.net/package/PEAR
 * @since      File available since Release 0.1
 *
 * TODO: log output parameters in PECL command line
 * TODO: msdev path in configuration
 */

/**
 * Needed for extending PEAR_Builder
 */
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';

/**
 * Class to handle building (compiling) extensions.
 *
 * @category   pear
 * @package    PEAR
 * @author     Stig Bakken <ssb@php.net>
 * @author     Greg Beaver <cellog@php.net>
 * @copyright  1997-2009 The Authors
 * @license    http://opensource.org/licenses/bsd-license.php New BSD License
 * @version    Release: 1.9.4
 * @link       http://pear.php.net/package/PEAR
 * @since      Class available since PHP 4.0.2
 * @see        http://pear.php.net/manual/en/core.ppm.pear-builder.php
 */
class PEAR_Builder extends PEAR_Common
{
    var $php_api_version = 0;
    var $zend_module_api_no = 0;
    var $zend_extension_api_no = 0;

    var $extensions_built = array();

    /**
     * @var string Used for reporting when it is not possible to pass function
     *             via extra parameter, e.g. log, msdevCallback
     */
    var $current_callback = null;

    // used for msdev builds
    var $_lastline = null;
    var $_firstline = null;

    /**
     * PEAR_Builder constructor.
     *
     * @param object $ui user interface object (instance of PEAR_Frontend_*)
     *
     * @access public
     */
    function PEAR_Builder(&$ui)
    {
        parent::PEAR_Common();
        $this->setFrontendObject($ui);
    }

    /**
     * Build an extension from source on windows.
     * requires msdev
     */
    function _build_win32($descfile, $callback = null)
    {
        if (is_object($descfile)) {
            $pkg = $descfile;
            $descfile = $pkg->getPackageFile();
        } else {
            $pf = &new PEAR_PackageFile($this->config, $this->debug);
            $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
            if (PEAR::isError($pkg)) {
                return $pkg;
            }
        }
        $dir = dirname($descfile);
        $old_cwd = getcwd();

        if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
            return $this->raiseError("could not chdir to $dir");
        }

        // packages that were in a .tar have the packagefile in this directory
        $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        if (file_exists($dir) && is_dir($vdir)) {
            if (!chdir($vdir)) {
                return $this->raiseError("could not chdir to " . realpath($vdir));
            }

            $dir = getcwd();
        }

        $this->log(2, "building in $dir");

        $dsp = $pkg->getPackage().'.dsp';
        if (!file_exists("$dir/$dsp")) {
            return $this->raiseError("The DSP $dsp does not exist.");
        }
        // XXX TODO: make release build type configurable
        $command = 'msdev '.$dsp.' /MAKE "'.$pkg->getPackage(). ' - Release"';

        $err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
        if (PEAR::isError($err)) {
            return $err;
        }

        // figure out the build platform and type
        $platform = 'Win32';
        $buildtype = 'Release';
        if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
            $platform = $matches[1];
            $buildtype = $matches[2];
        }

        if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/', $this->_lastline, $matches)) {
            if ($matches[2]) {
                // there were errors in the build
                return $this->raiseError("There were errors during compilation.");
            }
            $out = $matches[1];
        } else {
            return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
        }

        // msdev doesn't tell us the output directory :/
        // open the dsp, find /out and use that directory
        $dsptext = join(file($dsp),'');

        // this regex depends on the build platform and type having been
        // correctly identified above.
        $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
                    $pkg->getPackage().'\s-\s'.
                    $platform.'\s'.
                    $buildtype.'").*?'.
                    '\/out:"(.*?)"/is';

        if ($dsptext && preg_match($regex, $dsptext, $matches)) {
            // what we get back is a relative path to the output file itself.
            $outfile = realpath($matches[2]);
        } else {
            return $this->raiseError("Could not retrieve output information from $dsp.");
        }
        // realpath returns false if the file doesn't exist
        if ($outfile && copy($outfile, "$dir/$out")) {
            $outfile = "$dir/$out";
        }

        $built_files[] = array(
            'file' => "$outfile",
            'php_api' => $this->php_api_version,
            'zend_mod_api' => $this->zend_module_api_no,
            'zend_ext_api' => $this->zend_extension_api_no,
            );

        return $built_files;
    }
    // }}}

    // {{{ msdevCallback()
    function msdevCallback($what, $data)
    {
        if (!$this->_firstline)
            $this->_firstline = $data;
        $this->_lastline = $data;
        call_user_func($this->current_callback, $what, $data);
    }

    /**
     * @param string
     * @param string
     * @param array
     * @access private
     */
    function _harvestInstDir($dest_prefix, $dirname, &$built_files)
    {
        $d = opendir($dirname);
        if (!$d)
            return false;

        $ret = true;
        while (($ent = readdir($d)) !== false) {
            if ($ent{0} == '.')
                continue;

            $full = $dirname . DIRECTORY_SEPARATOR . $ent;
            if (is_dir($full)) {
                if (!$this->_harvestInstDir(
                        $dest_prefix . DIRECTORY_SEPARATOR . $ent,
                        $full, $built_files)) {
                    $ret = false;
                    break;
                }
            } else {
                $dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
                $built_files[] = array(
                        'file' => $full,
                        'dest' => $dest,
                        'php_api' => $this->php_api_version,
                        'zend_mod_api' => $this->zend_module_api_no,
                        'zend_ext_api' => $this->zend_extension_api_no,
                        );
            }
        }
        closedir($d);
        return $ret;
    }

    /**
     * Build an extension from source.  Runs "phpize" in the source
     * directory, but compiles in a temporary directory
     * (TMPDIR/pear-build-USER/PACKAGE-VERSION).
     *
     * @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
     *               a PEAR_PackageFile object
     *
     * @param mixed $callback callback function used to report output,
     * see PEAR_Builder::_runCommand for details
     *
     * @return array an array of associative arrays with built files,
     * format:
     * array( array( 'file' => '/path/to/ext.so',
     *               'php_api' => YYYYMMDD,
     *               'zend_mod_api' => YYYYMMDD,
     *               'zend_ext_api' => YYYYMMDD ),
     *        ... )
     *
     * @access public
     *
     * @see PEAR_Builder::_runCommand
     */
    function build($descfile, $callback = null)
    {
        if (preg_match('/(\\/|\\\\|^)([^\\/\\\\]+)?php(.+)?$/',
                       $this->config->get('php_bin'), $matches)) {
            if (isset($matches[2]) && strlen($matches[2]) &&
                trim($matches[2]) != trim($this->config->get('php_prefix'))) {
                $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                           ' appears to have a prefix ' . $matches[2] . ', but' .
                           ' config variable php_prefix does not match');
            }

            if (isset($matches[3]) && strlen($matches[3]) &&
                trim($matches[3]) != trim($this->config->get('php_suffix'))) {
                $this->log(0, 'WARNING: php_bin ' . $this->config->get('php_bin') .
                           ' appears to have a suffix ' . $matches[3] . ', but' .
                           ' config variable php_suffix does not match');
            }
        }

        $this->current_callback = $callback;
        if (PEAR_OS == "Windows") {
            return $this->_build_win32($descfile, $callback);
        }

        if (PEAR_OS != 'Unix') {
            return $this->raiseError("building extensions not supported on this platform");
        }

        if (is_object($descfile)) {
            $pkg = $descfile;
            $descfile = $pkg->getPackageFile();
            if (is_a($pkg, 'PEAR_PackageFile_v1')) {
                $dir = dirname($descfile);
            } else {
                $dir = $pkg->_config->get('temp_dir') . '/' . $pkg->getName();
                // automatically delete at session end
                $this->addTempFile($dir);
            }
        } else {
            $pf = &new PEAR_PackageFile($this->config);
            $pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
            if (PEAR::isError($pkg)) {
                return $pkg;
            }
            $dir = dirname($descfile);
        }

        // Find config. outside of normal path - e.g. config.m4
        foreach (array_keys($pkg->getInstallationFileList()) as $item) {
          if (stristr(basename($item), 'config.m4') && dirname($item) != '.') {
            $dir .= DIRECTORY_SEPARATOR . dirname($item);
            break;
          }
        }

        $old_cwd = getcwd();
        if (!file_exists($dir) || !is_dir($dir) || !chdir($dir)) {
            return $this->raiseError("could not chdir to $dir");
        }

        $vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
        if (is_dir($vdir)) {
            chdir($vdir);
        }

        $dir = getcwd();
        $this->log(2, "building in $dir");
        putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
        $err = $this->_runCommand($this->config->get('php_prefix')
                                . "phpize" .
                                $this->config->get('php_suffix'),
                                array(&$this, 'phpizeCallback'));
        if (PEAR::isError($err)) {
            return $err;
        }

        if (!$err) {
            return $this->raiseError("`phpize' failed");
        }

        // {{{ start of interactive part
        $configure_command = "$dir/configure";
        $configure_options = $pkg->getConfigureOptions();
        if ($configure_options) {
            foreach ($configure_options as $o) {
                $default = array_key_exists('default', $o) ? $o['default'] : null;
                list($r) = $this->ui->userDialog('build',
                                                 array($o['prompt']),
                                                 array('text'),
                                                 array($default));
                if (substr($o['name'], 0, 5) == 'with-' &&
                    ($r == 'yes' || $r == 'autodetect')) {
                    $configure_command .= " --$o[name]";
                } else {
                    $configure_command .= " --$o[name]=".trim($r);
                }
            }
        }
        // }}} end of interactive part

        // FIXME make configurable
        if (!$user=getenv('USER')) {
            $user='defaultuser';
        }

        $tmpdir = $this->config->get('temp_dir');
        $build_basedir = System::mktemp(' -t "' . $tmpdir . '" -d "pear-build-' . $user . '"');
        $build_dir = "$build_basedir/$vdir";
        $inst_dir = "$build_basedir/install-$vdir";
        $this->log(1, "building in $build_dir");
        if (is_dir($build_dir)) {
            System::rm(array('-rf', $build_dir));
        }

        if (!System::mkDir(array('-p', $build_dir))) {
            return $this->raiseError("could not create build dir: $build_dir");
        }

        $this->addTempFile($build_dir);
        if (!System::mkDir(array('-p', $inst_dir))) {
            return $this->raiseError("could not create temporary install dir: $inst_dir");
        }
        $this->addTempFile($inst_dir);

        $make_command = getenv('MAKE') ? getenv('MAKE') : 'make';

        $to_run = array(
            $configure_command,
            $make_command,
            "$make_command INSTALL_ROOT=\"$inst_dir\" install",
            "find \"$inst_dir\" | xargs ls -dils"
            );
        if (!file_exists($build_dir) || !is_dir($build_dir) || !chdir($build_dir)) {
            return $this->raiseError("could not chdir to $build_dir");
        }
        putenv('PHP_PEAR_VERSION=1.9.4');
        foreach ($to_run as $cmd) {
            $err = $this->_runCommand($cmd, $callback);
            if (PEAR::isError($err)) {
                chdir($old_cwd);
                return $err;
            }
            if (!$err) {
                chdir($old_cwd);
                return $this->raiseError("`$cmd' failed");
            }
        }
        if (!($dp = opendir("modules"))) {
            chdir($old_cwd);
            return $this->raiseError("no `modules' directory found");
        }
        $built_files = array();
        $prefix = exec($this->config->get('php_prefix')
                        . "php-config" .
                       $this->config->get('php_suffix') . " --prefix");
        $this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
        chdir($old_cwd);
        return $built_files;
    }

    /**
     * Message callback function used when running the "phpize"
     * program.  Extracts the API numbers used.  Ignores other message
     * types than "cmdoutput".
     *
     * @param string $what the type of message
     * @param mixed $data the message
     *
     * @return void
     *
     * @access public
     */
    function phpizeCallback($what, $data)
    {
        if ($what != 'cmdoutput') {
            return;
        }
        $this->log(1, rtrim($data));
        if (preg_match('/You should update your .aclocal.m4/', $data)) {
            return;
        }
        $matches = array();
        if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
            $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
            $apino = (int)$matches[2];
            if (isset($this->$member)) {
                $this->$member = $apino;
                //$msg = sprintf("%-22s : %d", $matches[1], $apino);
                //$this->log(1, $msg);
            }
        }
    }

    /**
     * Run an external command, using a message callback to report
     * output.  The command will be run through popen and output is
     * reported for every line with a "cmdoutput" message with the
     * line string, including newlines, as payload.
     *
     * @param string $command the command to run
     *
     * @param mixed $callback (optional) function to use as message
     * callback
     *
     * @return bool whether the command was successful (exit code 0
     * means success, any other means failure)
     *
     * @access private
     */
    function _runCommand($command, $callback = null)
    {
        $this->log(1, "running: $command");
        $pp = popen("$command 2>&1", "r");
        if (!$pp) {
            return $this->raiseError("failed to run `$command'");
        }
        if ($callback && $callback[0]->debug == 1) {
            $olddbg = $callback[0]->debug;
            $callback[0]->debug = 2;
        }

        while ($line = fgets($pp, 1024)) {
            if ($callback) {
                call_user_func($callback, 'cmdoutput', $line);
            } else {
                $this->log(2, rtrim($line));
            }
        }
        if ($callback && isset($olddbg)) {
            $callback[0]->debug = $olddbg;
        }

        $exitcode = is_resource($pp) ? pclose($pp) : -1;
        return ($exitcode == 0);
    }

    function log($level, $msg)
    {
        if ($this->current_callback) {
            if ($this->debug >= $level) {
                call_user_func($this->current_callback, 'output', $msg);
            }
            return;
        }
        return PEAR_Common::log($level, $msg);
    }
}


<?php

namespace Reaction\Annotations;

use Doctrine\Common\Annotations\Annotation\Attribute;
use Doctrine\Common\Annotations\Annotation\Attributes;
use Reaction\Promise\ExtendedPromiseInterface;
use Reaction\RequestApplicationInterface;
use function Reaction\Promise\any;
use function Reaction\Promise\reject;
use function Reaction\Promise\resolve;
use Reaction\Web\User;

/**
 * @Annotation
 * @Target({"METHOD", "CLASS"})
 * @Attributes({
 *   @Attribute("authorized", type = "bool"),
 *   @Attribute("permissions",  type = "array"),
 * })
 *
 * Class Auth. Auth validation for controller or action
 * @package Reaction\Annotations
 */
class CtrlAuth implements CtrlActionValidatorInterface
{
    /**
     * @var array Permissions to check
     */
    public $permissions = [];
    /**
     * @var bool Only logged users / anonymous.
     * If 'true' then only logged in users is permitted, 'false' - only anonymous
     */
    public $authorized;

    /**
     * Validation callback
     * @param RequestApplicationInterface $app
     * @return ExtendedPromiseInterface
     */
    public function validate(RequestApplicationInterface $app)
    {
        $this->processPermissions();
        if (empty($this->permissions)) {
            return resolve(true);
        }
        $promises = [];
        foreach ($this->permissions as $permissionName) {
            $promises[] = $app->user->can($permissionName);
        }
        return !empty($promises) ? any($promises) : reject(false);
    }

    /**
     * Process permissions
     */
    protected function processPermissions()
    {
        $permissions = (array)$this->permissions;
        if (isset($this->authorized)) {
            $loggedInPermission = $this->authorized ? User::PERMISSION_LOGGED_IN : User::PERMISSION_NOT_LOGGED_IN;
            array_unshift($permissions, $loggedInPermission);
        }
        $this->permissions = array_unique($permissions, SORT_STRING);
    }
}


<?php namespace RestGalleries\APIs;

use Illuminate\Support\Fluent;
use RestGalleries\Auth\AuthAdapter;
use RestGalleries\Auth\OhmyAuth\OhmyAuth;
use RestGalleries\Exception\AuthException;
use RestGalleries\Interfaces\UserAdapter;

/**
 * Makes the hard work for the user classes of the different APIs.
 */
abstract class ApiUser implements UserAdapter
{
    /**
     * Url where to get the account details..
     *
     * @var string
     */
    protected $checkUrl;

    /**
     * OAuth request endpoint.
     *
     * @var string
     */
    protected $urlRequest;

    /**
     * OAuth authorization endpoint.
     *
     * @var string
     */
    protected $urlAuthorize;

    /**
     * OAuth access endpoint.
     *
     * @var string
     */
    protected $urlAccess;

    /**
     * Makes all the OAuth process to connect the app with the API, only, with the client credentials, the oauth endpoints urls, and an URL to get the user data and token credentials.
     *
     * @param  array $clientCredentials
     * @return \Illuminate\Support\Fluent
     */
    public function connect(array $clientCredentials)
    {
        $endPoints = array_filter([
            'request'   => $this->urlRequest,
            'authorize' => $this->urlAuthorize,
            'access'    => $this->urlAccess,
        ]);

        $auth = $this->newAuth();
        $data = $auth::connect($clientCredentials, $endPoints, $this->checkUrl);

        return $this->getUserOrFail($data);

    }

    /**
     * Checks the token credentials and returns an object with the data (and tokens) from the user account.
     * If for any reason the credentials are invalid, throws an exception.
     *
     * @param  array $tokenCredentials
     * @return \Illuminate\Support\Fluent
     */
    public function verifyCredentials(array $tokenCredentials)
    {
        $auth = $this->newAuth();
        $data = $auth::verifyCredentials($tokenCredentials, $this->checkUrl);

        return $this->getUserOrFail($data);

    }

    /**
     * Object builder to create and use the Auth client.
     * In this case, is set up as default OhmyAuth authentication client.
     *
     * @param  \RestGalleries\Auth\AuthAdapter $auth
     * @return \RestGalleries\Auth\AuthAdapter
     */
    public function newAuth(AuthAdapter $auth = null)
    {
        if (empty($auth)) {
            $auth = new OhmyAuth;
        }

        return $auth;

    }

    /**
     * Gets an array of account data and returns an object. If it not get user data throws an exception.
     *
     * @param  object $data
     * @throws \RestGalleries\Exception\AuthException
     * @return \Illuminate\Support\Fluent
     */
    protected function getUserOrFail($data)
    {
        if (! $user = $this->extractUserArray($data)) {
            throw new AuthException('The credentials are not valid or are obsolete.');
        }

        return new Fluent($user);

    }

    /**
     * Normalize request given data into an array.
     *
     * @param  object $data
     * @return array|boolean
     */
    abstract protected function extractUserArray($data);

}


<?php namespace Ordercloud\Requests\Handlers;

use Ordercloud\Requests\Exceptions\OrdercloudRequestException;
use Ordercloud\Requests\Exceptions\ResponseParseException;
use Ordercloud\Requests\OrdercloudRequest;
use Ordercloud\Support\ExceptionGenerators\ExceptionGeneratorService;
use Ordercloud\Support\Http\Client;
use Ordercloud\Support\Http\Response;
use Ordercloud\Support\Http\UrlParameteriser;
use Ordercloud\Support\Reflection\EntityReflector;
use Ordercloud\Support\Reflection\Exceptions\EntityParseException;

abstract class AbstractRequestHandler extends OrdercloudRequestHandler
{
    protected $method;
    private $url;
    private $queryParameters = [];
    private $bodyParameters = [];
    private $formParameters = [];
    private $headers = [];
    private $entityClass;
    private $entityDataKey = null;
    /**
     * @var UrlParameteriser
     */
    private $parameteriser;

    public function __construct(Client $client, ExceptionGeneratorService $exceptionGenerator, UrlParameteriser $parameteriser)
    {
        parent::__construct($client, $exceptionGenerator);
        $this->parameteriser = $parameteriser;
    }

    /**
     * @param $request
     */
    abstract protected function configure($request);

    /**
     * @param OrdercloudRequest $request
     *
     * @return mixed|Response
     * @throws OrdercloudRequestException
     * @throws ResponseParseException
     */
    public function handle($request)
    {
        $this->configure($request);

        $response = parent::handle(
            new OrdercloudRequest($this->method, $this->getUrl(), $this->getParameters(), $this->getHeaders())
        );

        try {
            return $this->transformResponse($response);
        }
        catch (EntityParseException $e) {
            throw new ResponseParseException($response, $e);
        }
    }

    /**
     * @param Response $response
     *
     * @return mixed
     */
    protected function transformResponse($response)
    {
        // TODO this needs to get out

        if ($this->entityDataKey) {
            return EntityReflector::parseAll($this->entityClass, $response->getData($this->entityDataKey));
        }

        if ($this->entityClass) {
            return EntityReflector::parse($this->entityClass, $response->getData());
        }

        return $response;
    }

    /**
     * Set the url. Optionally apply the sprintf function to
     * the url supplied by a variable number of arguments.
     *
     * @param string $url
     * @param mixed  $args [optional]
     *
     * @return static
     */
    protected function setUrl($url, $args = null)
    {
        $this->url = call_user_func_array('sprintf', func_get_args());

        return $this;
    }

    /**
     * Set the parameters that should be passed via url.
     *
     * @param array $queryParameters
     *
     * @return static
     */
    public function setQueryParameters(array $queryParameters)
    {
        $this->queryParameters = $queryParameters;

        return $this;
    }

    /**
     * Set parameters that should be passed via body.
     *
     * @param array $bodyParameters
     *
     * @return static
     */
    public function setBodyParameters(array $bodyParameters)
    {
        $this->bodyParameters = $bodyParameters;

        return $this;
    }

    /**
     * Set parameters that should be passed via form encoded body.
     *
     * @param array $formParameters
     *
     * @return static
     */
    public function setFormParameters(array $formParameters)
    {
        $this->formParameters = $formParameters;

        return $this;
    }

    /**
     * Set a parameter that should be passed via body.
     *
     * @param string $key
     * @param mixed  $value
     *
     * @return static
     */
    protected function setBodyParameter($key, $value)
    {
        $this->bodyParameters[$key] = $value;

        return $this;
    }

    /**
     * Set a parameter that should be passed via url.
     *
     * @param string $key
     * @param string $value
     *
     * @return static
     */
    protected function setQueryParameter($key, $value)
    {
        $this->queryParameters[$key] = $value;

        return $this;
    }

    /**
     * Set a parameter that should be passed via form encoded body.
     *
     * @param string $key
     * @param string $value
     *
     * @return static
     */
    protected function setFormParameter($key, $value)
    {
        $this->formParameters[$key] = $value;

        return $this;
    }

    /**
     * @param array $headers
     *
     * @return static
     */
    protected function setHeaders($headers)
    {
        $this->headers = $headers;

        return $this;
    }

    /**
     * @param string $key
     * @param string $value
     *
     * @return static
     */
    protected function setHeader($key, $value)
    {
        $this->headers[$key] = $value;

        return $this;
    }

    /**
     * @param string $className
     *
     * @return static
     */
    protected function setEntityClass($className)
    {
        $this->entityClass = $className;

        return $this;
    }

    /**
     * @param string $className
     *
     * @return static
     */
    protected function setEntityArrayClass($className)
    {
        return $this->setEntityClass($className)
            ->setEntityDataKey('results');
    }

    /**
     * @param string $entityDataKey
     *
     * @return static
     */
    public function setEntityDataKey($entityDataKey)
    {
        $this->entityDataKey = $entityDataKey;

        return $this;
    }

    /**
     * @return string
     */
    private function getUrl()
    {
        if (empty($this->queryParameters)) {
            return $this->url;
        }

        return $this->parameteriser->appendParametersToUrl($this->queryParameters, $this->url);
    }

    /**
     * @return array
     */
    private function getParameters()
    {
        if ( ! empty($this->formParameters)) {
            return $this->formParameters;
        }

        return $this->bodyParameters;
    }

    private function getHeaders()
    {
        if ( ! empty($this->formParameters)) {
            $this->setHeader('Content-type', 'application/x-www-form-urlencoded');
        }

        return $this->headers;
    }
}


<?php
/**
 * Zend Framework
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.zend.com/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@zend.com so we can send you a copy immediately.
 *
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 * @version    $Id: Rename.php 24593 2012-01-05 20:35:02Z matthew $
 */

/**
 * @see Zend_Filter_Interface
 */

/**
 * @category   Zend
 * @package    Zend_Filter
 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 */
class Zend_Filter_File_Rename implements Zend_Filter_Interface
{
    /**
     * Internal array of array(source, target, overwrite)
     */
    protected $_files = array();

    /**
     * Class constructor
     *
     * Options argument may be either a string, a Zend_Config object, or an array.
     * If an array or Zend_Config object, it accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Target file or directory to be renamed
     * @param  string $target Source filename or directory (deprecated)
     * @param  bool $overwrite Should existing files be overwritten (deprecated)
     * @return void
     */
    public function __construct($options)
    {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();
        } elseif (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {

            throw new Zend_Filter_Exception('Invalid options argument provided to filter');
        }

        if (1 < func_num_args()) {
            $argv = func_get_args();
            array_shift($argv);
            $source    = array_shift($argv);
            $overwrite = false;
            if (!empty($argv)) {
                $overwrite = array_shift($argv);
            }
            $options['source']    = $source;
            $options['overwrite'] = $overwrite;
        }

        $this->setFile($options);
    }

    /**
     * Returns the files to rename and their new name and location
     *
     * @return array
     */
    public function getFile()
    {
        return $this->_files;
    }

    /**
     * Sets a new file or directory as target, deleting existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return Zend_Filter_File_Rename
     */
    public function setFile($options)
    {
        $this->_files = array();
        $this->addFile($options);

        return $this;
    }

    /**
     * Adds a new file or directory as target to the existing ones
     *
     * Array accepts the following keys:
     * 'source'    => Source filename or directory which will be renamed
     * 'target'    => Target filename or directory, the new name of the sourcefile
     * 'overwrite' => Shall existing files be overwritten ?
     *
     * @param  string|array $options Old file or directory to be rewritten
     * @return Zend_Filter_File_Rename
     */
    public function addFile($options)
    {
        if (is_string($options)) {
            $options = array('target' => $options);
        } elseif (!is_array($options)) {

            throw new Zend_Filter_Exception ('Invalid options to rename filter provided');
        }

        $this->_convertOptions($options);

        return $this;
    }

    /**
     * Returns only the new filename without moving it
     * But existing files will be erased when the overwrite option is true
     *
     * @param  string  $value  Full path of file to change
     * @param  boolean $source Return internal informations
     * @return string The new filename which has been set
     */
    public function getNewName($value, $source = false)
    {
        $file = $this->_getFileName($value);
        if ($file['source'] == $file['target']) {
            return $value;
        }

        if (!file_exists($file['source'])) {
            return $value;
        }

        if (($file['overwrite'] == true) && (file_exists($file['target']))) {
            unlink($file['target']);
        }

        if (file_exists($file['target'])) {

            throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. It already exists.", $value));
        }

        if ($source) {
            return $file;
        }

        return $file['target'];
    }

    /**
     * Defined by Zend_Filter_Interface
     *
     * Renames the file $value to the new name set before
     * Returns the file $value, removing all but digit characters
     *
     * @param  string $value Full path of file to change
     * @throws Zend_Filter_Exception
     * @return string The new filename which has been set, or false when there were errors
     */
    public function filter($value)
    {
        $file   = $this->getNewName($value, true);
        if (is_string($file)) {
            return $file;
        }

        $result = rename($file['source'], $file['target']);

        if ($result === true) {
            return $file['target'];
        }

        throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. An error occured while processing the file.", $value));
    }

    /**
     * Internal method for creating the file array
     * Supports single and nested arrays
     *
     * @param  array $options
     * @return array
     */
    protected function _convertOptions($options) {
        $files = array();
        foreach ($options as $key => $value) {
            if (is_array($value)) {
                $this->_convertOptions($value);
                continue;
            }

            switch ($key) {
                case "source":
                    $files['source'] = (string) $value;
                    break;

                case 'target' :
                    $files['target'] = (string) $value;
                    break;

                case 'overwrite' :
                    $files['overwrite'] = (boolean) $value;
                    break;

                default:
                    break;
            }
        }

        if (empty($files)) {
            return $this;
        }

        if (empty($files['source'])) {
            $files['source'] = '*';
        }

        if (empty($files['target'])) {
            $files['target'] = '*';
        }

        if (empty($files['overwrite'])) {
            $files['overwrite'] = false;
        }

        $found = false;
        foreach ($this->_files as $key => $value) {
            if ($value['source'] == $files['source']) {
                $this->_files[$key] = $files;
                $found              = true;
            }
        }

        if (!$found) {
            $count                = count($this->_files);
            $this->_files[$count] = $files;
        }

        return $this;
    }

    /**
     * Internal method to resolve the requested source
     * and return all other related parameters
     *
     * @param  string $file Filename to get the informations for
     * @return array
     */
    protected function _getFileName($file)
    {
        $rename = array();
        foreach ($this->_files as $value) {
            if ($value['source'] == '*') {
                if (!isset($rename['source'])) {
                    $rename           = $value;
                    $rename['source'] = $file;
                }
            }

            if ($value['source'] == $file) {
                $rename = $value;
            }
        }

        if (!isset($rename['source'])) {
            return $file;
        }

        if (!isset($rename['target']) or ($rename['target'] == '*')) {
            $rename['target'] = $rename['source'];
        }

        if (is_dir($rename['target'])) {
            $name = basename($rename['source']);
            $last = $rename['target'][strlen($rename['target']) - 1];
            if (($last != '/') and ($last != '\\')) {
                $rename['target'] .= DIRECTORY_SEPARATOR;
            }

            $rename['target'] .= $name;
        }

        return $rename;
    }
}


<?php

/**
 * @file
 * A Phing task to run Drush commands.
 */

require_once "phing/Task.php";

class DrushParam
{

    private $value;

    public function addText($str)
    {
        $this->value = $str;
    }

    public function getValue()
    {
        return $this->value;
    }

}

class DrushOption
{

    private $name;
    private $value;

    public function setName($str)
    {
        $this->name = $str;
    }

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

    public function addText($str)
    {
        $this->value = $str;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function toString()
    {
        $name = $this->getName();
        $value = $this->getValue();
        $str = '--' . $name;
        if (!empty($value)) {
            $str .= '=' . $value;
        }

        return $str;
    }

}

class DrushTask extends Task
{

    /**
     * The message passed in the buildfile.
     */
    private $command = [];
    private $bin = null;
    private $alias = null;
    private $uri = null;
    private $dir = null;
    private $root = null;
    private $assume = null;
    private $simulate = false;
    private $pipe = false;
    private $options = [];
    private $params = [];
    private $return_property = null;
    private $verbose = false;
    private $haltonerror = true;
    private $passthru = false;
    private $logoutput = true;

    /**
     * The Drush command to run.
     */
    public function setCommand($str)
    {
        $this->command = $str;
    }

    /**
     * Path the Drush executable.
     */
    public function setBin($str)
    {
        $this->bin = $str;
    }

    /**
     * Drush alias to use.
     */
    public function setAlias($str)
    {
        $this->alias = $str;
    }

    /**
     * Drupal working directory to use.
     */
    public function setDir($str)
    {
        $this->dir = $str;
    }

    /**
     * Drupal root directory to use.
     */
    public function setRoot($str)
    {
        $this->root = $str;
    }

    /**
     * URI of the Drupal to use.
     */
    public function setUri($str)
    {
        $this->uri = $str;
    }

    /**
     * Assume 'yes' or 'no' to all prompts.
     */
    public function setAssume($var)
    {
        if ($var === "") {
            unset($this->assume);
        } elseif (is_string($var)) {
            $this->assume = ($var === 'yes' || $var === 'true');
        } else {
            $this->assume = !!$var;
        }
    }

    /**
     * Simulate all relevant actions.
     */
    public function setSimulate($var)
    {
        if (is_string($var)) {
            $var = strtolower($var);
            $this->simulate = ($var === 'yes' || $var === 'true');
        } else {
            $this->simulate = !!$var;
        }
    }

    /**
     * Use the pipe option.
     */
    public function setPipe($var)
    {
        if (is_string($var)) {
            $var = strtolower($var);
            $this->pipe = ($var === 'yes' || $var === 'true');
        } else {
            $this->pipe = !!$var;
        }
    }

    /**
     * The name of a Phing property to assign the Drush command's output to.
     */
    public function setReturnProperty($str)
    {
        $this->return_property = $str;
    }

    /**
     * The name of a Phing property to assign the Drush command's output to.
     */
    public function setHaltonerror($var)
    {
        if (is_string($var)) {
            $var = strtolower($var);
            $this->haltonerror = ($var === 'yes' || $var === 'true');
        } else {
            $this->haltonerror = !!$var;
        }
    }

    /**
     * Parameters for the Drush command.
     */
    public function createParam()
    {
        $o = new DrushParam();
        $this->params[] = $o;

        return $o;
    }

    /**
     * Options for the Drush command.
     */
    public function createOption()
    {
        $o = new DrushOption();
        $this->options[] = $o;

        return $o;
    }

    /**
     * Display extra information about the command.
     */
    public function setVerbose($var)
    {
        if (is_string($var)) {
            $this->verbose = ($var === 'yes' || $var === 'true');
        } else {
            $this->verbose = !!$var;
        }
    }

    /**
     * Use passthru() rather than exec() for command execution.
     */
    public function setPassthru($var)
    {
        if (is_string($var)) {
            $this->passthru = ($var === 'yes' || $var === 'true');
        } else {
            $this->passthru = !!$var;
        }
    }

    /**
     * Log output.
     */
    public function setLogOutput($var)
    {
        if (is_string($var)) {
            $this->logoutput = ($var === 'yes' || $var === 'true');
        } else {
            $this->logoutput = !!$var;
        }
    }

    /**
     * Initialize the task.
     */
    public function init()
    {
        // Get default root, uri and binary from project.
        $this->root = $this->getProject()->getProperty('drush.root');
        $this->uri = $this->getProject()->getProperty('drush.uri');
        $this->bin = $this->getProject()->getProperty('drush.bin');
        $this->dir = $this->getProject()->getProperty('drush.dir');
        $this->alias = $this->getProject()->getProperty('drush.alias');
        $this->setVerbose($this->getProject()->getProperty('drush.verbose'));
        $this->setAssume($this->getProject()->getProperty('drush.assume'));
        $this->setPassthru($this->getProject()->getProperty('drush.passthru'));
        $this->setLogOutput($this->getProject()->getProperty('drush.logoutput'));
    }

    /**
     * The main entry point method.
     */
    public function main()
    {
        $command = [];

        $command[] = !empty($this->bin) ? $this->bin : 'drush';

        if (!empty($this->alias)) {
            $command[] = '@' . $this->alias;
        }

        if (!empty($this->root)) {
            $option = new DrushOption();
            $option->setName('root');
            $option->addText($this->root);
            $this->options[] = $option;
        }

        if (!empty($this->uri)) {
            $option = new DrushOption();
            $option->setName('uri');
            $option->addText($this->uri);
            $this->options[] = $option;
        }

        if (is_bool($this->assume)) {
            $option = new DrushOption();
            $option->setName(($this->assume ? 'yes' : 'no'));
            $this->options[] = $option;
        }

        if ($this->simulate) {
            $option = new DrushOption();
            $option->setName('simulate');
            $this->options[] = $option;
        }

        if ($this->pipe) {
            $option = new DrushOption();
            $option->setName('pipe');
            $this->options[] = $option;
        }

        if (Phing::getMsgOutputLevel() >= Project::MSG_VERBOSE) {
            $this->setVerbose('true');
        }

        if ($this->verbose) {
            $option = new DrushOption();
            $option->setName('verbose');
            $this->options[] = $option;
            $exec_level = Project::MSG_INFO;
        } else {
            $exec_level = Project::MSG_VERBOSE;
        }

        foreach ($this->options as $option) {
            $command[] = $option->toString();
        }

        $command[] = $this->command;

        foreach ($this->params as $param) {
            $command[] = $param->getValue();
        }

        if (!empty($this->dir)) {
            $this->log("Changing working directory to: $this->dir", $exec_level);
            $initial_cwd = getcwd();
            chdir($this->dir);
        }

        // Execute Drush.
        $output = [];
        $return = null;

        if ($this->passthru) {
            $command = implode(' ', $command);
            $this->log("Executing: $command", $exec_level);
            passthru($command, $return);
        } else {
            // Redirect sterr to stout for Phing log.
            $command[] = '2>&1';

            $command = implode(' ', $command);
            $this->log("Executing: $command", $exec_level);
            exec($command, $output, $return);

            if ($this->logoutput) {
                // Collect Drush output for display through Phing's log.
                foreach ($output as $line) {
                    $this->log($line);
                }
            }
        }

        if (isset($initial_cwd)) {
            $this->log("Changing working directory back to $initial_cwd.", $exec_level);
            chdir($initial_cwd);
        }

        // Set value of the return property.
        if (!empty($this->return_property)) {
            $this->getProject()->setProperty($this->return_property, $return);
        }
        // Build fail.
        if ($this->haltonerror && $return != 0) {
            throw new BuildException("Drush exited with code $return");
        }

        return $return != 0;
    }

}


<?php
/**
 * Phergie (http://phergie.org)
 *
 * @link https://github.com/phergie/phergie-irc-plugin-react-command for the canonical source repository
 * @copyright Copyright (c) 2008-2014 Phergie Development Team (http://phergie.org)
 * @license http://phergie.org/license Simplified BSD License
 * @package Phergie\Irc\Plugin\React\Command
 */

namespace Phergie\Irc\Plugin\React\Command;

use Phergie\Irc\Event\UserEvent;
use Phergie\Irc\Event\UserEventInterface;

/**
 * Class for an event containing a command.
 *
 * @category Phergie
 * @package Phergie\Irc\Plugin\React\Command
 */
class CommandEvent extends UserEvent implements CommandEventInterface
{
    /**
     * Name of the parsed command
     *
     * @var string|null
     */
    protected $customCommand;

    /**
     * Parsed command parameter values
     *
     * @var array
     */
    protected $customParams = array();

    /**
     * Returns the name of the parsed command.
     *
     * @return string
     */
    public function getCustomCommand()
    {
        return $this->customCommand;
    }

    /**
     * Sets the name of the parsed command.
     *
     * @param string $customCommand
     */
    public function setCustomCommand($customCommand)
    {
        $this->customCommand = $customCommand;
    }

    /**
     * Returns parsed command parameter values.
     *
     * @return array
     */
    public function getCustomParams()
    {
        return $this->customParams;
    }

    /**
     * Sets parsed command parameter values.
     *
     * @param array $customParams
     */
    public function setCustomParams(array $customParams)
    {
        $this->customParams = $customParams;
    }

    /**
     * Copies data from an existing event into this one.
     *
     * @param \Phergie\Irc\Event\UserEventInterface $event
     */
    public function fromEvent(UserEventInterface $event)
    {
        // EventInterface
        $this->setMessage($event->getMessage());
        $this->setConnection($event->getConnection());
        $this->setParams($event->getParams());
        $this->setCommand($event->getCommand());

        // UserEventInterface
        $this->setPrefix($event->getPrefix());
        $this->setNick($event->getNick());
        $this->setUsername($event->getUsername());
        $this->setHost($event->getHost());
        $this->setTargets($event->getTargets());
    }
}


<?php

namespace Think\Image\Driver;

use Think\BaseException;
use Think\Image;
use Think\Image\IImage;

/**
 * Class Gd
 * @package Think\Image\Driver
 * @todo gif
 */
class Gd implements IImage
{
    /**
     * 图像资源对象
     * @var resource
     */
    private $img;

    /**
     * 图像信息，包括width,height,type,mime,size
     * @var array
     */
    private $info;

    /**
     * 构造方法，可用于打开一张图像
     *
     * @param string $imgname 图像路径
     */
    public function __construct($imgname = null)
    {
        $imgname && $this->open($imgname);
    }

    /**
     * 打开一张图像
     *
     * @param  string $imgname 图像路径
     * @throws BaseException
     */
    public function open($imgname)
    {
        //检测图像文件
        if (!is_file($imgname)) {
            throw new BaseException('不存在的图像文件');
        }

        //获取图像信息
        $_info = getimagesize($imgname);

        //检测图像合法性
        if (false === $_info || (IMAGETYPE_GIF === $_info[2] && empty($_info['bits']))) {
            throw new BaseException('非法图像文件');
        }

        //设置图像信息
        $this->info = [
            'width'  => $_info[0],
            'height' => $_info[1],
            'type'   => image_type_to_extension($_info[2], false),
            'mime'   => $_info['mime'],
        ];

        //销毁已存在的图像
        empty($this->img) || imagedestroy($this->img);

        //打开图像
        //@todo gif支持
        if ('gif' == $this->info['type']) {
            $class = 'Think\\Image\\Driver\\GIF';
            $this->gif = new $class($imgname);
            $this->img = imagecreatefromstring($this->gif->image());
        } else {
            $fun = "imagecreatefrom{$this->info['type']}";
            $this->img = $fun($imgname);
        }
    }

    /**
     * 保存图像
     *
     * @param  string $imgname 图像保存名称
     * @param  string $type 图像类型
     * @param  int $quality 图像质量
     * @param  bool $interlace 是否对JPEG类型图像设置隔行扫描
     * @throws BaseException
     */
    public function save($imgname, $type = null, $quality = 80, $interlace = true)
    {
        if (empty($this->img)) {
            throw new BaseException('没有可以被保存的图像资源');
        }

        //自动获取图像类型
        if (is_null($type)) {
            $type = $this->info['type'];
        } else {
            $type = strtolower($type);
        }
        //保存图像
        if ('jpeg' == $type || 'jpg' == $type) {
            //JPEG图像设置隔行扫描
            imageinterlace($this->img, $interlace);
            imagejpeg($this->img, $imgname, $quality);
        } elseif ('gif' == $type && !empty($this->gif)) {
            $this->gif->save($imgname);
        } else {
            $fun = 'image'.$type;
            $fun($this->img, $imgname);
        }
    }

    /**
     * 返回图像宽度
     * @return int 图像宽度
     * @throws BaseException
     */
    public function width()
    {
        if (empty($this->img)) {
            throw new BaseException('没有指定图像资源');
        }

        return $this->info['width'];
    }

    /**
     * 返回图像高度
     * @return int 图像高度
     * @throws BaseException
     */
    public function height()
    {
        if (empty($this->img)) {
            throw new BaseException('没有指定图像资源');
        }

        return $this->info['height'];
    }

    /**
     * 返回图像类型
     * @return string 图像类型
     * @throws BaseException
     */
    public function type()
    {
        if (empty($this->img)) {
            throw new BaseException('没有指定图像资源');
        }

        return $this->info['type'];
    }

    /**
     * 返回图像MIME类型
     * @return string 图像MIME类型
     * @throws BaseException
     */
    public function mime()
    {
        if (empty($this->img)) {
            throw new BaseException('没有指定图像资源');
        }

        return $this->info['mime'];
    }

    /**
     * 返回图像尺寸数组 0 - 图像宽度，1 - 图像高度
     * @return array 图像尺寸
     * @throws BaseException
     */
    public function size()
    {
        if (empty($this->img)) {
            throw new BaseException('没有指定图像资源');
        }

        return [$this->info['width'], $this->info['height']];
    }

    /**
     * 裁剪图像
     *
     * @param  int $w 裁剪区域宽度
     * @param  int $h 裁剪区域高度
     * @param  int $x 裁剪区域x坐标
     * @param  int $y 裁剪区域y坐标
     * @param  int $width 图像保存宽度
     * @param  int $height 图像保存高度
     * @throws BaseException
     */
    public function crop($w, $h, $x = 0, $y = 0, $width = null, $height = null)
    {
        if (empty($this->img)) {
            throw new BaseException('没有可以被裁剪的图像资源');
        }

        //设置保存尺寸
        empty($width) && $width = $w;
        empty($height) && $height = $h;

        do {
            //创建新图像
            $_img = imagecreatetruecolor($width, $height);
            // 调整默认颜色
            $color = imagecolorallocate($_img, 255, 255, 255);
            imagefill($_img, 0, 0, $color);

            //裁剪
            imagecopyresampled($_img, $this->img, 0, 0, $x, $y, $width, $height, $w, $h);
            imagedestroy($this->img); //销毁原图

            //设置新图像
            $this->img = $_img;
        } while (!empty($this->gif) && $this->gifNext());

        $this->info['width'] = $width;
        $this->info['height'] = $height;
    }

    /**
     * 生成缩略图
     *
     * @param  int $width 缩略图最大宽度
     * @param  int $height 缩略图最大高度
     * @param int $type 缩略图裁剪类型
     * @throws BaseException
     */
    public function thumb($width, $height, $type = Image::IMAGE_THUMB_SCALE)
    {
        if (empty($this->img)) {
            throw new BaseException('没有可以被缩略的图像资源');
        }

        //原图宽度和高度
        $w = $this->info['width'];
        $h = $this->info['height'];

        /* 计算缩略图生成的必要参数 */
        switch ($type) {
            /* 等比例缩放 */
            case Image::IMAGE_THUMB_SCALE:
                //原图尺寸小于缩略图尺寸则不进行缩略
                if ($w < $width && $h < $height) {
                    return;
                }

                //计算缩放比例
                $scale = min($width / $w, $height / $h);

                //设置缩略图的坐标及宽度和高度
                $x = $y = 0;
                $width = $w * $scale;
                $height = $h * $scale;
                break;

            /* 居中裁剪 */
            case Image::IMAGE_THUMB_CENTER:
                //计算缩放比例
                $scale = max($width / $w, $height / $h);

                //设置缩略图的坐标及宽度和高度
                $w = $width / $scale;
                $h = $height / $scale;
                $x = ($this->info['width'] - $w) / 2;
                $y = ($this->info['height'] - $h) / 2;
                break;

            /* 左上角裁剪 */
            case Image::IMAGE_THUMB_NORTHWEST:
                //计算缩放比例
                $scale = max($width / $w, $height / $h);

                //设置缩略图的坐标及宽度和高度
                $x = $y = 0;
                $w = $width / $scale;
                $h = $height / $scale;
                break;

            /* 右下角裁剪 */
            case Image::IMAGE_THUMB_SOUTHEAST:
                //计算缩放比例
                $scale = max($width / $w, $height / $h);

                //设置缩略图的坐标及宽度和高度
                $w = $width / $scale;
                $h = $height / $scale;
                $x = $this->info['width'] - $w;
                $y = $this->info['height'] - $h;
                break;

            /* 填充 */
            case Image::IMAGE_THUMB_FILLED:
                //计算缩放比例
                if ($w < $width && $h < $height) {
                    $scale = 1;
                } else {
                    $scale = min($width / $w, $height / $h);
                }

                //设置缩略图的坐标及宽度和高度
                $neww = $w * $scale;
                $newh = $h * $scale;
                $posx = ($width - $w * $scale) / 2;
                $posy = ($height - $h * $scale) / 2;

                do {
                    //创建新图像
                    $_img = imagecreatetruecolor($width, $height);
                    // 调整默认颜色
                    $color = imagecolorallocate($_img, 255, 255, 255);
                    imagefill($_img, 0, 0, $color);

                    //裁剪
                    imagecopyresampled($_img, $this->img, $posx, $posy, $x, $y, $neww, $newh, $w, $h);
                    imagedestroy($this->img); //销毁原图
                    $this->img = $_img;
                } while (!empty($this->gif) && $this->gifNext());

                $this->info['width'] = $width;
                $this->info['height'] = $height;

                return;

            /* 固定 */
            case Image::IMAGE_THUMB_FIXED:
                $x = $y = 0;
                break;

            default:
                throw new BaseException('不支持的缩略图裁剪类型');
        }

        /* 裁剪图像 */
        $this->crop($w, $h, $x, $y, $width, $height);
    }

    /**
     * 添加水印
     *
     * @param  string $source 水印图片路径
     * @param int $locate 水印位置
     * @param  int $alpha 水印透明度
     * @throws BaseException
     */
    public function water($source, $locate = Image::IMAGE_WATER_SOUTHEAST, $alpha = 80)
    {
        //资源检测
        if (empty($this->img)) {
            throw new BaseException('没有可以被添加水印的图像资源');
        }
        if (!is_file($source)) {
            throw new BaseException('水印图像不存在');
        }

        //获取水印图像信息
        $_info = getimagesize($source);
        if (false === $_info || (IMAGETYPE_GIF === $_info[2] && empty($_info['bits']))) {
            throw new BaseException('非法水印文件');
        }

        //创建水印图像资源
        $fun = 'imagecreatefrom'.image_type_to_extension($_info[2], false);
        $water = $fun($source);

        //设定水印图像的混色模式
        imagealphablending($water, true);

        /* 设定水印位置 */
        switch ($locate) {
            /* 右下角水印 */
            case Image::IMAGE_WATER_SOUTHEAST:
                $x = $this->info['width'] - $_info[0];
                $y = $this->info['height'] - $_info[1];
                break;

            /* 左下角水印 */
            case Image::IMAGE_WATER_SOUTHWEST:
                $x = 0;
                $y = $this->info['height'] - $_info[1];
                break;

            /* 左上角水印 */
            case Image::IMAGE_WATER_NORTHWEST:
                $x = $y = 0;
                break;

            /* 右上角水印 */
            case Image::IMAGE_WATER_NORTHEAST:
                $x = $this->info['width'] - $_info[0];
                $y = 0;
                break;

            /* 居中水印 */
            case Image::IMAGE_WATER_CENTER:
                $x = ($this->info['width'] - $_info[0]) / 2;
                $y = ($this->info['height'] - $_info[1]) / 2;
                break;

            /* 下居中水印 */
            case Image::IMAGE_WATER_SOUTH:
                $x = ($this->info['width'] - $_info[0]) / 2;
                $y = $this->info['height'] - $_info[1];
                break;

            /* 右居中水印 */
            case Image::IMAGE_WATER_EAST:
                $x = $this->info['width'] - $_info[0];
                $y = ($this->info['height'] - $_info[1]) / 2;
                break;

            /* 上居中水印 */
            case Image::IMAGE_WATER_NORTH:
                $x = ($this->info['width'] - $_info[0]) / 2;
                $y = 0;
                break;

            /* 左居中水印 */
            case Image::IMAGE_WATER_WEST:
                $x = 0;
                $y = ($this->info['height'] - $_info[1]) / 2;
                break;

            default:
                /* 自定义水印坐标 */
                if (is_array($locate)) {
                    list($x, $y) = $locate;
                } else {
                    throw new BaseException('不支持的水印位置类型');
                }
        }

        do {
            //添加水印
            $src = imagecreatetruecolor($_info[0], $_info[1]);
            // 调整默认颜色
            $color = imagecolorallocate($src, 255, 255, 255);
            imagefill($src, 0, 0, $color);

            imagecopy($src, $this->img, 0, 0, $x, $y, $_info[0], $_info[1]);
            imagecopy($src, $water, 0, 0, 0, 0, $_info[0], $_info[1]);
            imagecopymerge($this->img, $src, $x, $y, 0, 0, $_info[0], $_info[1], $alpha);

            //销毁零时图片资源
            imagedestroy($src);
        } while (!empty($this->gif) && $this->gifNext());

        //销毁水印资源
        imagedestroy($water);
    }

    /**
     * 图像添加文字
     *
     * @param  string $text 添加的文字
     * @param  string $font 字体路径
     * @param  int $size 字号
     * @param  string $color 文字颜色
     * @param int $locate 文字写入位置
     * @param  int $offset 文字相对当前位置的偏移量
     * @param  int $angle 文字倾斜角度
     * @throws BaseException
     */
    public function text(
        $text,
        $font,
        $size,
        $color = '#00000000',
        $locate = Image::IMAGE_WATER_SOUTHEAST,
        $offset = 0,
        $angle = 0
    ) {
        //资源检测
        if (empty($this->img)) {
            throw new BaseException('没有可以被写入文字的图像资源');
        }
        if (!is_file($font)) {
            throw new BaseException("不存在的字体文件：{$font}");
        }

        //获取文字信息
        $_info = imagettfbbox($size, $angle, $font, $text);
        $minx = min($_info[0], $_info[2], $_info[4], $_info[6]);
        $maxx = max($_info[0], $_info[2], $_info[4], $_info[6]);
        $miny = min($_info[1], $_info[3], $_info[5], $_info[7]);
        $maxy = max($_info[1], $_info[3], $_info[5], $_info[7]);

        /* 计算文字初始坐标和尺寸 */
        $x = $minx;
        $y = abs($miny);
        $w = $maxx - $minx;
        $h = $maxy - $miny;

        /* 设定文字位置 */
        switch ($locate) {
            /* 右下角文字 */
            case Image::IMAGE_WATER_SOUTHEAST:
                $x += $this->info['width'] - $w;
                $y += $this->info['height'] - $h;
                break;

            /* 左下角文字 */
            case Image::IMAGE_WATER_SOUTHWEST:
                $y += $this->info['height'] - $h;
                break;

            /* 左上角文字 */
            case Image::IMAGE_WATER_NORTHWEST:
                // 起始坐标即为左上角坐标，无需调整
                break;

            /* 右上角文字 */
            case Image::IMAGE_WATER_NORTHEAST:
                $x += $this->info['width'] - $w;
                break;

            /* 居中文字 */
            case Image::IMAGE_WATER_CENTER:
                $x += ($this->info['width'] - $w) / 2;
                $y += ($this->info['height'] - $h) / 2;
                break;

            /* 下居中文字 */
            case Image::IMAGE_WATER_SOUTH:
                $x += ($this->info['width'] - $w) / 2;
                $y += $this->info['height'] - $h;
                break;

            /* 右居中文字 */
            case Image::IMAGE_WATER_EAST:
                $x += $this->info['width'] - $w;
                $y += ($this->info['height'] - $h) / 2;
                break;

            /* 上居中文字 */
            case Image::IMAGE_WATER_NORTH:
                $x += ($this->info['width'] - $w) / 2;
                break;

            /* 左居中文字 */
            case Image::IMAGE_WATER_WEST:
                $y += ($this->info['height'] - $h) / 2;
                break;

            default:
                /* 自定义文字坐标 */
                if (is_array($locate)) {
                    list($posx, $posy) = $locate;
                    $x += $posx;
                    $y += $posy;
                } else {
                    throw new BaseException('不支持的文字位置类型');
                }
        }

        /* 设置偏移量 */
        if (is_array($offset)) {
            $offset = array_map('intval', $offset);
            list($ox, $oy) = $offset;
        } else {
            $offset = intval($offset);
            $ox = $oy = $offset;
        }

        /* 设置颜色 */
        if (is_string($color) && 0 === strpos($color, '#')) {
            $color = str_split(substr($color, 1), 2);
            $color = array_map('hexdec', $color);
            if (empty($color[3]) || $color[3] > 127) {
                $color[3] = 0;
            }
        } elseif (!is_array($color)) {
            throw new BaseException('错误的颜色值');
        }

        do {
            /* 写入文字 */
            $col = imagecolorallocatealpha($this->img, $color[0], $color[1], $color[2], $color[3]);
            imagettftext($this->img, $size, $angle, $x + $ox, $y + $oy, $col, $font, $text);
        } while (!empty($this->gif) && $this->gifNext());
    }

    /**
     * 切换到GIF的下一帧并保存当前帧，内部使用
     * @return bool
     */
    private function gifNext()
    {
        ob_start();
        ob_implicit_flush(0);
        imagegif($this->img);
        $_img = ob_get_clean();

        $this->gif->image($_img);
        $next = $this->gif->nextImage();

        if ($next) {
            $this->img = imagecreatefromstring($next);

            return $next;
        } else {
            $this->img = imagecreatefromstring($this->gif->image());

            return false;
        }
    }

    /**
     * 析构方法，用于销毁图像资源
     */
    public function __destruct()
    {
        empty($this->img) || imagedestroy($this->img);
    }
}


<?php
/**
 * Cacheable Trait
 *
 * @author Del
 */

namespace Delatbabel\Keylists\Models;

use Delatbabel\Fluents\Fluents;
use Illuminate\Support\Facades\Cache;

/**
 * Cacheable Trait
 *
 * This trait can be applied to any model class allowing the
 * caching of the entire database table.  Note that it stores
 * the entire table contents in a single cache object, which
 * is usually suitable for tables containing small amounts of
 * data such as key/value pairs, category lists, etc.
 *
 * Caching in this manner is usually only efficient if the data
 * in the table is small and rarely changes.
 */
trait Cacheable
{
    use Fluents;

    /** @var string contains the cache key for caching values */
    // protected static $cache_key = 'override.this.key';

    /**
     * Override this function to provide the cache key.
     *
     * Note that using a protected static variable inside a trait can't
     * be done, it throws an error whenever it is overriden.
     */
    abstract protected function cacheKey();

    /**
     * Return the cache key for a model.
     *
     * Override this in child classes.
     *
     * @return string
     */
    abstract protected function getIndexKey();

    /**
     * Return a simple list of entries in the table.
     *
     * May cache the results for up to 60 minutes.
     *
     * @return	array of Fluent objects
     */
    public static function tableToArray()
    {
        $me        = new static();
        $cache_key = $me->cacheKey();

        // Return the array from the cache if it is present.
        if (Cache::has($cache_key)) {
            return (array) Cache::get($cache_key);
        }

        // Otherwise put the results into the cache and return them.
        $results = [];

        $query = static::all();

        // If the current model uses softDeletes then fix the
        // query to exclude those objects.
        foreach (class_uses(__CLASS__) as $traitName) {
            if ($traitName == 'SoftDeletes') {
                $query = static::whereNull('deleted_at')->get();
                break;
            }
        }

        /** @var Cacheable $row */
        foreach ($query as $row) {
            $results[$row->getIndexKey()] = $row->toFluent();
        }
        Cache::put($cache_key, $results, 60);
        return $results;
    }

    /**
     * Discard the cache for any tableToArray call.
     *
     * @return void
     */
    public static function discardTableToArray()
    {
        $me        = new static();
        $cache_key = $me->cacheKey();

        Cache::forget($cache_key);
    }
}


<?php
/**
 * Список элементов
 *
 * @version ${product.version}
 *
 * @copyright 2011, Михаил Красильников <mihalych@vsepofigu.ru>
 * @license http://www.gnu.org/licenses/gpl.txt	GPL License 3
 * @author Михаил Красильников <mihalych@vsepofigu.ru>
 *
 * Данная программа является свободным программным обеспечением. Вы
 * вправе распространять ее и/или модифицировать в соответствии с
 * условиями версии 3 либо (по вашему выбору) с условиями более поздней
 * версии Стандартной Общественной Лицензии GNU, опубликованной Free
 * Software Foundation.
 *
 * Мы распространяем эту программу в надежде на то, что она будет вам
 * полезной, однако НЕ ПРЕДОСТАВЛЯЕМ НА НЕЕ НИКАКИХ ГАРАНТИЙ, в том
 * числе ГАРАНТИИ ТОВАРНОГО СОСТОЯНИЯ ПРИ ПРОДАЖЕ и ПРИГОДНОСТИ ДЛЯ
 * ИСПОЛЬЗОВАНИЯ В КОНКРЕТНЫХ ЦЕЛЯХ. Для получения более подробной
 * информации ознакомьтесь со Стандартной Общественной Лицензией GNU.
 *
 * Вы должны были получить копию Стандартной Общественной Лицензии
 * GNU с этой программой. Если Вы ее не получили, смотрите документ на
 * <http://www.gnu.org/licenses/>
 *
 * @package UI
 */

/**
 * Список элементов
 *
 * Позволяет создавать многостраничные списки произвольных элементов, получаемых из различных
 * источников и оформлять их на основе произвольных шаблонов.
 *
 * Для получения данных используется специальный объект-посредник, реализующий интерфейс
 * {@link UI_List_DataProvider_Interface}.
 *
 * Можно задать размер страницы и номер текущей страницы списка при помощи {@link setPageSize()} и
 * {@link setPage()} соответственно.
 *
 * Для отрисовки списка надо передать в шаблон объект {@link UI_List}, а затем использовать
 * методы {@link getItems()}, {@link getPagination()} и {@link getControls()} для вставки в шаблон
 * соответствующих частей списка.
 *
 * Чтобы использовать в шаблоне переключатель страниц и другие элементы управления списком, надо
 * задать генератор адресов методом {@link setURL()}.
 *
 * Пример шаблона:
 *
 *
 * {if count($list->getItems())}
 *

 *   {foreach $list->getItems() item}
 *

 *     {$list->getControls($item, 'edit', 'toggle', 'delete')}
 *     {$item->foo}
 *     {$item->bar}
 *

 *   {/foreach}
 *

 * {$list->getPagination()->render()}
 * {/if}
 *
 *
 * @package UI
 */
class UI_List
{
    /**
     * Модуль
     *
     * @var Eresus_Plugin
     */
    private $plugin;

    /**
     * Поставщик данных
     *
     * @var UI_List_DataProvider_Interface
     */
    private $dataProvider;

    /**
     * Размер страницы
     *
     * @var int
     */
    private $pageSize;

    /**
     * Элементы списка
     *
     * @var array
     */
    private $items;

    /**
     * Корневой URL
     *
     * @var UI_List_URL_Interface
     */
    private $url;

    /**
     * Страница списка
     *
     * @var int
     */
    private $page = 1;

    /**
     * Переключатель страниц
     *
     * @var PaginationHelper
     */
    private $pagination = null;

    /**
     * Конструктор
     *
     * @param Eresus_Plugin                  $plugin    плагин-владелец
     * @param UI_List_DataProvider_Interface $provider  поставщик данных
     * @param UI_List_URL_Interface          $url       построитель адресов
     *
     * @return UI_List
     *
     * @since 1.00
     */
    public function __construct(Eresus_Plugin $plugin, UI_List_DataProvider_Interface $provider = null,
                                UI_List_URL_Interface $url = null)
    {
        $this->plugin = $plugin;
        if ($provider)
        {
            $this->setDataProvider($provider);
        }
        if ($url)
        {
            $this->setURL($url);
        }
    }

    /**
     * Возвращает поставщика данных
     *
     * @return UI_List_DataProvider_Interface
     *
     * @since 1.00
     */
    public function getDataProvider()
    {
        return $this->dataProvider;
    }

    /**
     * Устанавливает поставщика данных
     *
     * @param UI_List_DataProvider_Interface $provider
     *
     * @return void
     *
     * @since 1.00
     */
    public function setDataProvider(UI_List_DataProvider_Interface $provider)
    {
        $this->dataProvider = $provider;
    }

    /**
     * Возвращает построитель адресов
     *
     * @return UI_List_URL_Interface
     *
     * @since 1.00
     */
    public function getURL()
    {
        if (!$this->url)
        {
            $this->url =
                Eresus_Kernel::app()->getPage() instanceof TClientUI
                    ? new UI_List_URL_Client()
                    : new UI_List_URL_Query();
        }
        return $this->url;
    }

    /**
     * Устанавливает построитель адресов
     *
     * См. {@link UI_List_URL_Interface}
     *
     * @param UI_List_URL_Interface $url
     *
     * @return void
     *
     * @since 1.00
     */
    public function setURL(UI_List_URL_Interface $url)
    {
        $this->url = $url;
    }

    /**
     * Устанавливает номер текущей страницы списка
     *
     * @param int $page
     *
     * @return void
     *
     * @since 1.00
     */
    public function setPage($page)
    {
        $this->page = $page;
    }

    /**
     * Устанавливает размер страницы (в строках)
     *
     * @param int $size
     *
     * @return void
     *
     * @since 1.00
     */
    public function setPageSize($size)
    {
        $this->pageSize = $size;
    }

    /**
     * Возвращает массив элементов списка для подстановки в шаблон
     *
     * @return array
     *
     * @since 1.00
     */
    public function getItems()
    {
        if (is_null($this->items))
        {
            $this->items = $this->dataProvider->getItems($this->pageSize,
                ($this->page - 1) * $this->pageSize);
        }
        return $this->items;
    }

    /**
     * Возвращает переключатель страниц
     *
     * @return PaginationHelper
     *
     * @since 1.00
     */
    public function getPagination()
    {
        if (!$this->pagination)
        {
            $totalPages = $this->pageSize ? ceil($this->dataProvider->getCount() / $this->pageSize) : 0;
            $this->pagination = new PaginationHelper($totalPages, $this->page,
                $this->getURL()->getPagination());
        }
        return $this->pagination;
    }

    /**
     * Возвращает разметку элементов управления для использования в шаблоне
     *
     * Возможные имена ЭУ:
     *
     * - delete — Удаление
     * - edit — Изменение
     * - ordering — Переместить выше/ниже в списке
     * - toggle — Включить/Отключить
     *
     * Пример:
     *
     *
     * $list->getControls($item, 'delete', 'edit', 'toggle')
     *
     *
     * @param UI_List_Item_Interface $item           элемент списка, для которого нужны элементы управления
     *
     * @return string
     *
     * @since 1.00
     */
    public function getControls(UI_List_Item_Interface $item)
    {
        $controls = func_get_args();
        array_shift($controls);

        $html = '';

        if (in_array('edit', $controls))
        {
            $html .= $this->getControl_edit($item);
        }

        if (in_array('toggle', $controls))
        {
            $html .= $this->getControl_toggle($item);
        }

        if (in_array('ordering', $controls))
        {
            $html .= $this->getControl_ordering($item);
        }

        if (in_array('delete', $controls))
        {
            $html .= $this->getControl_delete($item);
        }

        return $html;
    }

    /**
     * Возвращает разметку ЭУ «Удалить»
     *
     * @param UI_List_Item_Interface $item  элемент списка, для которого нужно создать ЭУ
     *
     * @return string
     *
     * @since 1.00
     */
    private function getControl_delete(UI_List_Item_Interface $item)
    {
        /** @var TAdminUI $page */
        $page = Eresus_Kernel::app()->getPage();
        return 'getURL()->getDelete($item) . '" title="' . ADM_DELETE
            . '" onclick="return askdel(this);">root
            . $page->getUITheme()->getIcon('item-delete.png') . '" alt="' . ADM_DELETE . '"> ';
    }

    /**
     * Возвращает разметку ЭУ «Изменить»
     *
     * @param UI_List_Item_Interface $item  элемент списка, для которого нужно создать ЭУ
     *
     * @return string
     *
     * @since 1.00
     */
    private function getControl_edit(UI_List_Item_Interface $item)
    {
        /** @var TAdminUI $page */
        $page = Eresus_Kernel::app()->getPage();
        return 'getURL()->getEdit($item) . '" title="' . ADM_EDIT . '">root . $page->getUITheme()->getIcon('item-edit.png')
            . '" alt="' . ADM_EDIT . '"> ';
    }

    /**
     * Возвращает разметку ЭУ «Порядок следования»
     *
     * @param UI_List_Item_Interface $item  элемент списка, для которого нужно создать ЭУ
     *
     * @return string
     *
     * @since 1.00
     */
    private function getControl_ordering(UI_List_Item_Interface $item)
    {
        $rootUrl = Eresus_CMS::getLegacyKernel()->root;
        /** @var TAdminUI $page */
        $page = Eresus_Kernel::app()->getPage();

        return 'getURL()->getOrderingUp($item) . '" title="' . ADM_UP
            . '">getUITheme()->getIcon('move-up.png') . '" alt="' . ADM_UP
            . '"> getURL()->getOrderingDown($item) . '" title="' . ADM_DOWN
            . '">getUITheme()->getIcon('move-down.png') . '" alt="'
            . ADM_DOWN . '"> ';
    }

    /**
     * Возвращает разметку ЭУ «Активность»
     *
     * @param UI_List_Item_Interface $item  элемент списка, для которого нужно создать ЭУ
     *
     * @return string
     *
     * @since 1.00
     */
    private function getControl_toggle(UI_List_Item_Interface $item)
    {
        /** @var TAdminUI $page */
        $page = Eresus_Kernel::app()->getPage();
        return 'getURL()->getToggle($item) . '" title="'
            . ($item->isEnabled() ? ADM_DEACTIVATE : ADM_ACTIVATE ) . '">root . $page->getUITheme()->getIcon('item-'
            . ($item->isEnabled() ? 'active' : 'inactive') . '.png') . '" alt="'
            . ($item->isEnabled() ? ADM_ACTIVATED : ADM_DEACTIVATED ) . '"> ';
    }
}


<?php
namespace Core\Toolbox\Strings;

/**
 * IsSerialized.php
 *
 * @author Michael "Tekkla" Zorn <tekkla@tekkla.de>
 * @copyright 2016
 * @license MIT
 */
class IsSerialized extends AbstractStrings
{

    private $result;

    /**
     * Sets a reference to a result var which will be used to store the unserialized result when string is serialized
     *
     * @param mixed $result
     */
    public function setResult(&$result)
    {
        $this->result = $result;
    }

    /**
     * Tests if an input is valid PHP serialized string
     *
     * Checks if a string is serialized using quick string manipulation
     * to throw out obviously incorrect strings. Unserialize is then run
     * on the string to perform the final verification.
     *
     * Valid serialized forms are the following:
     *

     *
boolean: b:1;

     *
integer: i:1;

     *
double: d:0.2;

     *
string: s:4:"test";

     *
array: a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}

     *
object: O:8:"stdClass":0:{}

     *
null: N;

     *

     *
     * @return boolean if $value is serialized data, otherwise false
     */
    function isSerialized(): bool
    {
        // Empty strings cannot get unserialized
        if (strlen($this->string) <= 1) {
            return false;
        }

        // Serialized false, return true. unserialize() returns false on an
        // invalid string or it could return false if the string is serialized
        // false, eliminate that possibility.
        if ($this->string === 'b:0;') {
            $result = false;
            return true;
        }

        $length = strlen($this->string);
        $end = '';

        switch ($this->string[0]) {
            case 's':
                if ($this->string[$length - 2] !== '"') {
                    return false;
                }
            case 'b':
            case 'i':
            case 'd':
                $end .= ';';
            case 'a':
            case 'O':
                $end .= '}';

                if ($this->string[1] !== ':') {
                    return false;
                }

                switch ($this->string[2]) {
                    case 0:
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                    case 9:
                        break;

                    default:
                        return false;
                }
            case 'N':
                $end .= ';';

                if ($this->string[$length - 1] !== $end[0]) {
                    return false;
                }

                break;

            default:
                return false;
        }

        if (($this->result = @unserialize($this->string)) === false) {
            $this->result = null;
            return false;
        }

        return true;
    }
}


<?php

namespace Kcs\FunctionMock\Prediction;

use Kcs\FunctionMock\FunctionProphecy;
use Prophecy\Call\Call;

class CallbackPrediction implements PredictionInterface
{
    private $callback;

    /**
     * Initializes callback prediction.
     *
     * @param callable $callback Custom callback
     */
    public function __construct(callable $callback)
    {
        $this->callback = $callback;
    }

    /**
     * Executes preset callback.
     *
     * @param Call[]         $calls
     * @param FunctionProphecy $prophecy
     */
    public function check(array $calls, FunctionProphecy $prophecy)
    {
        $callback = $this->callback;
        call_user_func($callback, $calls, $prophecy);
    }
}


<?php

namespace Reaction\Routes;

use FastRoute\Dispatcher;
use Reaction;
use Reaction\Annotations\Ctrl;
use Reaction\Annotations\CtrlAction;
use Reaction\Base\Component;
use Reaction\Exceptions\InvalidConfigException;
use Reaction\Helpers\ClassFinderHelper;
use Reaction\Helpers\Inflector;
use Reaction\RequestApplicationInterface;

/**
 * Class RouterAbstract
 * @package Reaction\Routes
 */
abstract class RouterAbstract extends Component implements RouterInterface
{
    /**
     * @var string[]
     */
    public $controllerNamespaces = [
        'App\Controllers',
    ];

    /**
     * @var string Default controller if none matches
     */
    public $defaultController;

    /** @var array Added routes information */
    protected $routes = [];
    /** @var string Currently processed group */
    protected $groupCurrent = '';
    /** @var Dispatcher */
    protected $dispatcher;
    /** @var array Registered controllers */
    protected $controllers = [];
    /** @var array  Route path expressions. Used to build URLs */
    protected $_routePaths = [];

    /**
     * Add route handling
     * @param string|string[] $httpMethod
     * @param string $route
     * @param mixed $handler
     */
    public function addRoute($httpMethod, $route, $handler) {
        $route = $this->groupCurrent . $route;
        $this->routes[] = [
            'httpMethod' => $httpMethod,
            'route' => $route,
            'handler' => $handler,
        ];
    }

    /**
     * Add controller with its actions
     * @param Controller $controller
     */
    public function addController(Controller $controller) {
        $this->registerController($controller);
    }

    /**
     * Find controllers in given namespaces and register as routes
     */
    public function initRoutes()
    {
        $classNames = ClassFinderHelper::findClassesPsr4($this->controllerNamespaces, true);
        foreach ($classNames as $className) {
            $this->registerController($className);
        }
    }

    /**
     * Get controller and action from path (Just parse path)
     * @param string $path
     * @param array  $config
     * @param bool   $defaultOnFault
     * @return array
     */
    public function createController($path, $config = [], $defaultOnFault = true)
    {
        $path = trim($path, '/');
        $parts = explode('/', $path);
        if (count($parts) < 2) {
            if (!isset($parts[0]) || trim($parts[0]) === '') {
                return $defaultOnFault ? $this->getDefaultControllerAndAction($config) : [null, null];
            } else {
                $controllerName = mb_strtolower(array_pop($parts));
                $actionId = Controller::$_defaultAction;
            }
        } else {
            $actionId = mb_strtolower(array_pop($parts));
            $controllerName = mb_strtolower(array_pop($parts));
        }
        $controllerName = Inflector::id2camel($controllerName, '-') . 'Controller';
        if (!empty($parts)) {
            array_walk($parts, function(&$value) {
                $value = Inflector::id2camel($value, '-');
            });
            $controllerName = implode('\\', $parts) . '\\' . $controllerName;
        }
        list($controller, $actionId) = $this->createControllerInstance($controllerName, $actionId, $config);
        return $controller !== null
            ? [$controller, $actionId]
            : ($defaultOnFault ? $this->getDefaultControllerAndAction($config) : [null, null]);
    }

    /**
     * Get controller namespace relative to $this::$controllerNamespaces
     * @param string $namespace
     * @return string
     * @see $controllerNamespaces
     */
    public function getRelativeControllerNamespace($namespace)
    {
        $candidate = $namespace;
        foreach ($this->controllerNamespaces as $controllerNamespace) {
            if (strpos($namespace, $controllerNamespace) === 0) {
                $temp = ltrim(substr($namespace, strlen($controllerNamespace)), '\\');
                if (strlen($temp) < strlen($candidate)) {
                    $candidate = $temp;
                }
            }
        }
        return $candidate;
    }

    /**
     * Get router path expressions
     * @return array
     */
    public function getRoutePaths()
    {
        return isset($this->_routePaths) ? $this->_routePaths : [];
    }

    /**
     * Search for a given route
     * @param RequestApplicationInterface $app
     * @param string                      $routePath
     * @param string                      $method
     * @param bool                        $withInternal
     * @return array
     */
    abstract public function searchRoute(RequestApplicationInterface $app, $routePath, $method = 'GET', $withInternal = false);

    /**
     * Search controller by name and action ID
     * @param string|ControllerInterface $controllerName
     * @param string                     $actionId
     * @param array                      $config
     * @return array
     */
    protected function createControllerInstance($controllerName, $actionId = null, $config = [])
    {
        if (!isset($controllerName)) {
            return [null, $actionId];
        } elseif ($controllerName instanceof ControllerInterface) {
            $controller = $controllerName;
            if (!isset($actionId) || !$controller->hasAction($actionId)) {
                $actionId = $controller->defaultAction;
            }
            return [$controller, $actionId];
        }
        $controller = null;
        foreach ($this->controllerNamespaces as $namespace) {
            $controllerNameFull = $namespace . '\\' . $controllerName;
            if (!class_exists($controllerNameFull)) {
                continue;
            }
            try {
                /** @var ControllerInterface $controller */
                $config = Reaction\Helpers\ArrayHelper::merge($config, ['class' => $controllerNameFull]);
                $controller = Reaction::create($config);
                if (!isset($actionId) || !$controller->hasAction($actionId)) {
                    $actionId = $controller->defaultAction;
                }
                break;
            } catch (InvalidConfigException $exception) {
                $controller = null;
                continue;
            }
        }
        return [$controller, $actionId];
    }

    /**
     * Register controller in routes
     * @param string|Controller $className
     */
    protected function registerController($className) {
        $_className = is_string($className) ? $className : get_class($className);
        if (in_array($_className, $this->controllers)) {
            return;
        }
        $this->controllers[] = $_className;
        $classAnnotations = Reaction::$annotations->getClass($className);
        if (isset($classAnnotations[Ctrl::class])) {
            $this->registerControllerWithAnnotations($className, $classAnnotations[Ctrl::class]);
        } else {
            $this->registerControllerNoAnnotations($className);
        }
    }

    /**
     * Register controller that uses Annotations
     * @param string|Controller $className
     * @param Ctrl $ctrlAnnotation
     * @throws \ReflectionException
     */
    protected function registerControllerWithAnnotations($className, Ctrl $ctrlAnnotation) {
        $actions = (new \ReflectionClass($className))->getMethods(\ReflectionMethod::IS_PUBLIC);
        $actions = array_filter($actions, function($value) {
            return $value->name !== 'actions' && strpos($value->name, 'action') === 0 ? $value : false;
        });
        $actions = Reaction\Helpers\ArrayHelper::getColumn($actions, 'name', false);
        if (empty($actions)) {
            return;
        }
        $controller = is_string($className) ? new $className() : $className;
        for ($i = 0; $i < count($actions); $i++) {
            $actionAnnotations = Reaction::$annotations->getMethod($actions[$i], $className);
            if (!isset($actionAnnotations[CtrlAction::class])) {
                continue;
            }
            /** @var CtrlAction $ctrlAction */
            $ctrlAction = $actionAnnotations[CtrlAction::class];
            $path = $ctrlAnnotation->group . '/' . ltrim($ctrlAction->path, '/');
            $path = $path !== '/' ? rtrim($path, '/') : $path;
            $actionId = Controller::getActionId($actions[$i]);
            $this->addRoute($ctrlAction->method, $path, [$controller, $actionId]);
        }
    }

    /**
     * Register controller that does not use Annotations
     * @param string|Controller $className
     */
    protected function registerControllerNoAnnotations($className) {
        /** @var Controller $controller */
        $controller = new $className();
        $routes = $controller->routes();
        $group = $controller->group();
        if (empty($routes)) {
            return;
        }
        foreach ($routes as $row) {
            $method = $row['method'];
            $route = $group . $row['route'];
            $handlerName = $row['handler'];
            $actionId = Controller::getActionId($handlerName);
            $this->addRoute($method, $route, [$controller, $actionId]);
        }
    }

    /**
     * Get default action
     * @param array $config
     * @return array
     */
    protected function getDefaultControllerAndAction($config = [])
    {
        $controller = $action = null;
        if (isset($this->defaultController)) {
            /** @var ControllerInterface $controller */
            $configDefault = is_array($this->defaultController) ? $this->defaultController : ['class' => $this->defaultController];
            $config = Reaction\Helpers\ArrayHelper::merge($configDefault, $config);
            $controller = Reaction::create($config);
            $action = $controller->defaultAction;
        }
        return [$controller, $action];
    }
}


<?php

declare(strict_types=1);

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

namespace Teknoo\States\LifeCycle\StatedClass;

use Teknoo\States\LifeCycle\Observing\ObservedInterface;

/**
 * Class LifeCyclableTrait
 * Trait implementing LifeCyclableInterface to add lifecyclable and tracable behaviors on your stated class.
 *
 *
 * @copyright   Copyright (c) 2009-2017 Richard Déloge (richarddeloge@gmail.com)
 *
 * @link        http://teknoo.software/states Project website
 *
 * @license     http://teknoo.software/license/mit         MIT License
 * @author      Richard Déloge <richarddeloge@gmail.com>
 * @mixin LifeCyclableInterface
 */
trait LifeCyclableTrait
{
    /**
     * List of all observing relation manager.
     *
     * @var ObservedInterface[]
     */
    private $observedList = [];

    /**
     * To register a new observer.
     *
     * @param ObservedInterface $observed
     *
     * @return LifeCyclableInterface
     */
    public function registerObserver(ObservedInterface $observed): LifeCyclableInterface
    {
        $this->observedList[\spl_object_hash($observed)] = $observed;

        return $this;
    }

    /**
     * To unregister a previous registered observer.
     *
     * @param ObservedInterface $observed
     *
     * @return LifeCyclableInterface
     */
    public function unregisterObserver(ObservedInterface $observed): LifeCyclableInterface
    {
        $observedHash = \spl_object_hash($observed);

        if (isset($this->observedList[$observedHash])) {
            unset($this->observedList[$observedHash]);
        }

        return $this;
    }

    /**
     * To notify to observers that this instance has been changed.
     *
     * @return LifeCyclableInterface
     */
    public function notifyObserved(): LifeCyclableInterface
    {
        foreach ($this->observedList as $observed) {
            $observed->observeUpdate();
        }

        return $this;
    }
}


<?php
/*
 * This file is part of the Skeetr package.
 *
 * (c) Máximo Cuadros <mcuadros@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Skeetr\Client\Channels;

use Skeetr\Client;
use Skeetr\Client\Channel;

class ControlChannel extends Channel
{
    /**
     * Constructor
     *
     * @param Client $client
     * @param string $basename printf format, used in ControlChannel::autoSetChannel
     */
    public function __construct(Client $client, $basename)
    {
        parent::__construct($client);
        $this->autoSetChannel($basename);
    }

    /**
     * Set the channel name based on the basename given in the constructor
     *
     * @param string $channel
     */
    private function autoSetChannel($basename)
    {
        $channel = sprintf($basename, $this->client->getId());
        $this->setChannel($channel);
    }

    /**
     * {@inheritdoc}
     */
    public function process(\GearmanJob $job)
    {
        $start = microtime(true);

        $command = json_decode($job->workload(), true);

        $result = $this->executeCommand($command);
        $result['elapsed'] = microtime(true) - $start;

        return json_encode($result);
    }

    /**
     * Execute the command received from the Job
     *
     * @param  array $command
     * @return array the response
     */
    private function executeCommand($command)
    {
        if ( !is_array($command) || !isset($command['command']) ) {
            return $this->returnError('Malformed command received.');
        }

        switch ($command['command']) {
            case 'journal': return $this->commandJournal($command);
            case 'shutdown': return $this->commandShutdown($command);
            default: return $this->returnError('Unknown command.');
        }
    }

    /**
     * Return client's journal as array
     *
     * @param  array $command
     * @return array the response
     */
    private function commandJournal($options)
    {
        return $this->client->getJournal()->getData();
    }

    /**
     * Shutdown the client
     *
     * @param  array   $command
     * @return boolean the response
     */
    private function commandShutdown($options)
    {
        return array(
            'result' => $this->client->shutdown()
        );
    }

    /**
     * Return an error
     *
     * @param  string $message
     * @return array  the response
     */
    private function returnError($message)
    {
        return array(
            'error' => $message
        );
    }
}