Phalcon Framework 1.3.2

Elastica\Exception\ResponseException: SearchPhaseExecutionException[Failed to execute phase [query], all shards failed; shardFailures {[Krj3g1d7SbeUcYvhc8ioAw][torrentino_staging][3]: EsRejectedExecutionException[rejected execution (queue capacity 1000) on org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$4@f160fa5]}{[Krj3g1d7SbeUcYvhc8ioAw][torrentino_staging][2]: EsRejectedExecutionException[rejected execution (queue capacity 1000) on org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$4@7aeea2c9]}{[Krj3g1d7SbeUcYvhc8ioAw][torrentino_staging][5]: EsRejectedExecutionException[rejected execution (queue capacity 1000) on org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$4@243969a6]}{[Krj3g1d7SbeUcYvhc8ioAw][torrentino_staging][4]: EsRejectedExecutionException[rejected execution (queue capacity 1000) on org.elasticsearch.action.search.type.TransportSearchTypeAction$BaseAsyncAction$4@28af1ff2]}]

/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php (146)
#0Elastica\Transport\Http->exec(Object(Elastica\Request), Array([connection] => Array(13)))
<?php
 
namespace Elastica;
 
use Elastica\Exception\InvalidException;
use Elastica\JSON;
 
/**
 * Elastica Request object
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Request extends Param
{
    const HEAD = 'HEAD';
    const POST = 'POST';
    const PUT = 'PUT';
    const GET = 'GET';
    const DELETE = 'DELETE';
 
    /**
     * @var \Elastica\Connection
     */
    protected $_connection;
 
    /**
     * Construct
     *
     * @param string              $path       Request path
     * @param string              $method     OPTIONAL Request method (use const's) (default = self::GET)
     * @param array               $data       OPTIONAL Data array
     * @param array               $query      OPTIONAL Query params
     * @param Connection $connection
     * @return \Elastica\Request OPTIONAL Connection object
     */
    public function __construct($path, $method = self::GET, $data = array(), array $query = array(), Connection $connection = null)
    {
        $this->setPath($path);
        $this->setMethod($method);
        $this->setData($data);
        $this->setQuery($query);
 
        if ($connection) {
            $this->setConnection($connection);
        }
    }
 
    /**
     * Sets the request method. Use one of the for consts
     *
     * @param  string           $method Request method
     * @return \Elastica\Request Current object
     */
    public function setMethod($method)
    {
        return $this->setParam('method', $method);
    }
 
    /**
     * Get request method
     *
     * @return string Request method
     */
    public function getMethod()
    {
        return $this->getParam('method');
    }
 
    /**
     * Sets the request data
     *
     * @param  array            $data Request data
     * @return \Elastica\Request
     */
    public function setData($data)
    {
        return $this->setParam('data', $data);
    }
 
    /**
     * Return request data
     *
     * @return array Request data
     */
    public function getData()
    {
        return $this->getParam('data');
    }
 
    /**
     * Sets the request path
     *
     * @param  string           $path Request path
     * @return \Elastica\Request Current object
     */
    public function setPath($path)
    {
        return $this->setParam('path', $path);
    }
 
    /**
     * Return request path
     *
     * @return string Request path
     */
    public function getPath()
    {
        return $this->getParam('path');
    }
 
    /**
     * Return query params
     *
     * @return array Query params
     */
    public function getQuery()
    {
        return $this->getParam('query');
    }
 
    /**
     * @param  array            $query
     * @return \Elastica\Request
     */
    public function setQuery(array $query = array())
    {
        return $this->setParam('query', $query);
    }
 
    /**
     * @param  \Elastica\Connection $connection
     * @return \Elastica\Request
     */
    public function setConnection(Connection $connection)
    {
        $this->_connection = $connection;
 
        return $this;
    }
 
    /**
     * Return Connection Object
     *
     * @throws Exception\InvalidException
     * @return \Elastica\Connection
     */
    public function getConnection()
    {
        if (empty($this->_connection)) {
            throw new InvalidException('No valid connection object set');
        }
 
        return $this->_connection;
    }
 
    /**
     * Sends request to server
     *
     * @return \Elastica\Response Response object
     */
    public function send()
    {
        $transport = $this->getConnection()->getTransportObject();
 
        // Refactor: Not full toArray needed in exec?
        return $transport->exec($this, $this->getConnection()->toArray());
    }
 
    /**
     * @return array
     */
    public function toArray()
    {
        $data = $this->getParams();
        if ($this->_connection) {
            $data['connection'] = $this->_connection->getParams();
        }
        return $data;
    }
 
    /**
     * Converts request to curl request format
     *
     * @return string
     */
    public function toString()
    {
        return JSON::stringify($this->toArray());
    }
 
    /**
     * @return string
     */
    public function __toString()
    {
        return $this->toString();
    }
}
#1Elastica\Request->send()
<?php
 
namespace Elastica;
 
use Elastica\Bulk;
use Elastica\Bulk\Action;
use Elastica\Exception\ResponseException;
use Elastica\Exception\ClientException;
use Elastica\Exception\ConnectionException;
use Elastica\Exception\InvalidException;
use Elastica\Exception\RuntimeException;
use Psr\Log\LoggerInterface;
 
/**
 * Client to connect the the elasticsearch server
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Client
{
    /**
     * Config with defaults
     *
     * log: Set to true, to enable logging, set a string to log to a specific file
     * retryOnConflict: Use in \Elastica\Client::updateDocument
     *
     * @var array
     */
    protected $_config = array(
        'host'            => null,
        'port'            => null,
        'path'            => null,
        'url'             => null,
        'proxy'           => null,
        'transport'       => null,
        'persistent'      => true,
        'timeout'         => null,
        'connections'     => array(), // host, port, path, timeout, transport, persistent, timeout, config -> (curl, headers, url)
        'roundRobin'      => false,
        'log'             => false,
        'retryOnConflict' => 0,
    );
 
    /**
     * @var \Elastica\Connection[] List of connections
     */
    protected $_connections = array();
 
    /**
     * @var callback
     */
    protected $_callback = null;
 
    /**
     * @var \Elastica\Request
     */
    protected $_lastRequest;
 
    /**
     * @var \Elastica\Response
     */
    protected $_lastResponse;
 
    /**
     * @var LoggerInterface
     */
    protected $_logger = null;
 
    /**
     * Creates a new Elastica client
     *
     * @param array    $config   OPTIONAL Additional config options
     * @param callback $callback OPTIONAL Callback function which can be used to be notified about errors (for example connection down)
     */
    public function __construct(array $config = array(), $callback = null)
    {
        $this->setConfig($config);
        $this->_callback = $callback;
        $this->_initConnections();
    }
 
    /**
     * Inits the client connections
     */
    protected function _initConnections()
    {
        $connections = $this->getConfig('connections');
 
        foreach ($connections as $connection) {
            $this->_connections[] = Connection::create($this->_prepareConnectionParams($connection));
        }
 
        if (isset($this->_config['servers'])) {
            foreach ($this->getConfig('servers') as $server) {
                $this->_connections[] = Connection::create($this->_prepareConnectionParams($server));
            }
        }
 
        // If no connections set, create default connection
        if (empty($this->_connections)) {
            $this->_connections[] = Connection::create($this->_prepareConnectionParams($this->getConfig()));
        }
    }
 
    /**
     * Creates a Connection params array from a Client or server config array.
     *
     * @param array $config
     * @return array
     */
    protected function _prepareConnectionParams(array $config)
    {
        $params = array();
        $params['config'] = array();
        foreach ($config as $key => $value) {
            if (in_array($key, array('curl', 'headers', 'url'))) {
                $params['config'][$key] = $value;
            } else {
                $params[$key] = $value;
            }
        }
 
        return $params;
    }
 
    /**
     * Sets specific config values (updates and keeps default values)
     *
     * @param  array           $config Params
     * @return \Elastica\Client
     */
    public function setConfig(array $config)
    {
        foreach ($config as $key => $value) {
            $this->_config[$key] = $value;
        }
 
        return $this;
    }
 
    /**
     * Returns a specific config key or the whole
     * config array if not set
     *
     * @param  string                              $key Config key
     * @throws \Elastica\Exception\InvalidException
     * @return array|string                        Config value
     */
    public function getConfig($key = '')
    {
        if (empty($key)) {
            return $this->_config;
        }
 
        if (!array_key_exists($key, $this->_config)) {
            throw new InvalidException('Config key is not set: ' . $key);
        }
 
        return $this->_config[$key];
    }
 
    /**
     * Sets / overwrites a specific config value
     *
     * @param  string          $key   Key to set
     * @param  mixed           $value Value
     * @return \Elastica\Client Client object
     */
    public function setConfigValue($key, $value)
    {
        return $this->setConfig(array($key => $value));
    }
 
    /**
     * @param array|string $keys config key or path of config keys
     * @param mixed $default default value will be returned if key was not found
     * @return mixed
     */
    public function getConfigValue($keys, $default = null)
    {
        $value = $this->_config;
        foreach ((array) $keys as $key) {
            if (isset($value[$key])) {
                $value = $value[$key];
            } else {
                return $default;
            }
        }
        return $value;
    }
 
    /**
     * Returns the index for the given connection
     *
     * @param  string         $name Index name to create connection to
     * @return \Elastica\Index Index for the given name
     */
    public function getIndex($name)
    {
        return new Index($this, $name);
    }
 
    /**
     * Adds a HTTP Header
     *
     * @param  string                              $header      The HTTP Header
     * @param  string                              $headerValue The HTTP Header Value
     * @throws \Elastica\Exception\InvalidException If $header or $headerValue is not a string
     */
    public function addHeader($header, $headerValue)
    {
        if (is_string($header) && is_string($headerValue)) {
            $this->_config['headers'][$header] = $headerValue;
        } else {
            throw new InvalidException('Header must be a string');
        }
    }
 
    /**
     * Remove a HTTP Header
     *
     * @param  string                              $header The HTTP Header to remove
     * @throws \Elastica\Exception\InvalidException IF $header is not a string
     */
    public function removeHeader($header)
    {
        if (is_string($header)) {
            if (array_key_exists($header, $this->_config['headers'])) {
                unset($this->_config['headers'][$header]);
            }
        } else {
            throw new InvalidException('Header must be a string');
        }
    }
 
    /**
     * Uses _bulk to send documents to the server
     *
     * Array of \Elastica\Document as input. Index and type has to be
     * set inside the document, because for bulk settings documents,
     * documents can belong to any type and index
     *
     * @param  array|\Elastica\Document[]           $docs Array of Elastica\Document
     * @return \Elastica\Bulk\ResponseSet                   Response object
     * @throws \Elastica\Exception\InvalidException If docs is empty
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function updateDocuments(array $docs) {
        if (empty($docs)) {
            throw new InvalidException('Array has to consist of at least one element');
        }
 
        $bulk = new Bulk($this);
 
        $bulk->addDocuments($docs, \Elastica\Bulk\Action::OP_TYPE_UPDATE);
 
        return $bulk->send();
    }
 
    /**
     * Uses _bulk to send documents to the server
     *
     * Array of \Elastica\Document as input. Index and type has to be
     * set inside the document, because for bulk settings documents,
     * documents can belong to any type and index
     *
     * @param  array|\Elastica\Document[]           $docs Array of Elastica\Document
     * @return \Elastica\Bulk\ResponseSet                   Response object
     * @throws \Elastica\Exception\InvalidException If docs is empty
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function addDocuments(array $docs)
    {
        if (empty($docs)) {
            throw new InvalidException('Array has to consist of at least one element');
        }
 
        $bulk = new Bulk($this);
 
        $bulk->addDocuments($docs);
 
        return $bulk->send();
    }
 
    /**
     * Update document, using update script. Requires elasticsearch >= 0.19.0
     *
     * @param  int                  $id      document id
     * @param  array|\Elastica\Script|\Elastica\Document $data    raw data for request body
     * @param  string               $index   index to update
     * @param  string               $type    type of index to update
     * @param  array                $options array of query params to use for query. For possible options check es api
     * @return \Elastica\Response
     * @link http://www.elasticsearch.org/guide/reference/api/update.html
     */
    public function updateDocument($id, $data, $index, $type, array $options = array())
    {
        $path =  $index . '/' . $type . '/' . $id . '/_update';
 
        if ($data instanceof Script) {
            $requestData = $data->toArray();
 
        } elseif ($data instanceof Document) {
 
            $requestData = array('doc' => $data->getData());
 
            if ($data->getDocAsUpsert()) {
                $requestData['doc_as_upsert'] = true;
            }
 
            $docOptions = $data->getOptions(
                array(
                    'version',
                    'version_type',
                    'routing',
                    'percolate',
                    'parent',
                    'fields',
                    'retry_on_conflict',
                    'consistency',
                    'replication',
                    'refresh',
                    'timeout',
                )
            );
            $options += $docOptions;
            // set fields param to source only if options was not set before
            if ($data instanceof Document && ($data->isAutoPopulate()
                || $this->getConfigValue(array('document', 'autoPopulate'), false))
                && !isset($options['fields'])
            ) {
                $options['fields'] = '_source';
            }
        } else {
            $requestData = $data;
        }
 
        //If an upsert document exists
        if ($data instanceof Script || $data instanceof Document) {
 
            if ($data->hasUpsert()) {
                $requestData['upsert'] = $data->getUpsert()->getData();
            }
        }
 
        if (!isset($options['retry_on_conflict'])) {
            $retryOnConflict = $this->getConfig("retryOnConflict");
            $options['retry_on_conflict'] = $retryOnConflict;
        }
 
        $response = $this->request($path, Request::POST, $requestData, $options);
 
        if ($response->isOk()
            && $data instanceof Document
            && ($data->isAutoPopulate() || $this->getConfigValue(array('document', 'autoPopulate'), false))
        ) {
            $responseData = $response->getData();
            if (isset($responseData['_version'])) {
                $data->setVersion($responseData['_version']);
            }
            if (isset($options['fields'])) {
                $this->_populateDocumentFieldsFromResponse($response, $data, $options['fields']);
            }
        }
 
        return $response;
    }
 
    /**
     * @param \Elastica\Response $response
     * @param \Elastica\Document $document
     * @param string $fields Array of field names to be populated or '_source' if whole document data should be updated
     */
    protected function _populateDocumentFieldsFromResponse(Response $response, Document $document, $fields)
    {
        $responseData = $response->getData();
        if ('_source' == $fields) {
            if (isset($responseData['get']['_source']) && is_array($responseData['get']['_source'])) {
                $document->setData($responseData['get']['_source']);
            }
        } else {
            $keys = explode(',', $fields);
            $data = $document->getData();
            foreach ($keys as $key) {
                if (isset($responseData['get']['fields'][$key])) {
                    $data[$key] = $responseData['get']['fields'][$key];
                } elseif (isset($data[$key])) {
                    unset($data[$key]);
                }
            }
            $document->setData($data);
        }
    }
 
    /**
     * Bulk deletes documents
     *
     * @param array|\Elastica\Document[] $docs
     * @return \Elastica\Bulk\ResponseSet
     * @throws \Elastica\Exception\InvalidException
     */
    public function deleteDocuments(array $docs)
    {
        if (empty($docs)) {
            throw new InvalidException('Array has to consist of at least one element');
        }
 
        $bulk = new Bulk($this);
        $bulk->addDocuments($docs, Action::OP_TYPE_DELETE);
 
        return $bulk->send();
    }
 
    /**
     * Returns the status object for all indices
     *
     * @return \Elastica\Status Status object
     */
    public function getStatus()
    {
        return new Status($this);
    }
 
    /**
     * Returns the current cluster
     *
     * @return \Elastica\Cluster Cluster object
     */
    public function getCluster()
    {
        return new Cluster($this);
    }
 
    /**
     * @param  \Elastica\Connection $connection
     * @return \Elastica\Client
     */
    public function addConnection(Connection $connection)
    {
        $this->_connections[] = $connection;
 
        return $this;
    }
 
    /**
     * Determines whether a valid connection is available for use.
     * 
     * @return bool
     */
    public function hasConnection()
    {
        foreach ($this->_connections as $connection)
        {
            if ($connection->isEnabled())
            {
                return true;
            }
        }
        
        return false;
    }
 
    /**
     * @throws \Elastica\Exception\ClientException
     * @return \Elastica\Connection
     */
    public function getConnection()
    {
        $enabledConnection = null;
 
        foreach ($this->_connections as $connection) {
            if ($connection->isEnabled()) {
                $enabledConnection = $connection;
                break;
            }
        }
 
        if (empty($enabledConnection)) {
            throw new ClientException('No enabled connection');
        }
 
        return $enabledConnection;
    }
 
    /**
     * @return \Elastica\Connection[]
     */
    public function getConnections()
    {
        return $this->_connections;
    }
 
    /**
     * @param  \Elastica\Connection[] $connections
     * @return \Elastica\Client
     */
    public function setConnections(array $connections)
    {
        $this->_connections = $connections;
 
        return $this;
    }
 
    /**
     * Deletes documents with the given ids, index, type from the index
     *
     * @param  array                                $ids      Document ids
     * @param  string|\Elastica\Index               $index    Index name
     * @param  string|\Elastica\Type                $type     Type of documents
     * @param  string|false                         $routing  Optional routing key for all ids
     * @throws \Elastica\Exception\InvalidException
     * @return \Elastica\Bulk\ResponseSet           Response  object
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function deleteIds(array $ids, $index, $type, $routing = false)
    {
        if (empty($ids)) {
            throw new InvalidException('Array has to consist of at least one id');
        }
 
        $bulk = new Bulk($this);
        $bulk->setIndex($index);
        $bulk->setType($type);
 
        foreach ($ids as $id) {
            $action = new Action(Action::OP_TYPE_DELETE);
            $action->setId($id);
 
            if (!empty($routing)) {
                $action->setRouting($routing);
            }
 
            $bulk->addAction($action);
        }
 
        return $bulk->send();
    }
 
    /**
     * Bulk operation
     *
     * Every entry in the params array has to exactly on array
     * of the bulk operation. An example param array would be:
     *
     * array(
     *         array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')),
     *         array('user' => array('name' => 'hans')),
     *         array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2'))
     * );
     *
     * @param  array                                    $params Parameter array
     * @throws \Elastica\Exception\ResponseException
     * @throws \Elastica\Exception\InvalidException
     * @return \Elastica\Bulk\ResponseSet                        Response object
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function bulk(array $params)
    {
        if (empty($params)) {
            throw new InvalidException('Array has to consist of at least one param');
        }
 
        $bulk = new Bulk($this);
 
        $bulk->addRawData($params);
 
        return $bulk->send();
    }
 
    /**
     * Makes calls to the elasticsearch server based on this index
     *
     * It's possible to make any REST query directly over this method
     *
     * @param  string            $path   Path to call
     * @param  string            $method Rest method to use (GET, POST, DELETE, PUT)
     * @param  array             $data   OPTIONAL Arguments as array
     * @param  array             $query  OPTIONAL Query params
     * @throws Exception\ConnectionException|\Exception
     * @return \Elastica\Response Response object
     */
    public function request($path, $method = Request::GET, $data = array(), array $query = array())
    {
        $connection = $this->getConnection();
        try {
            $request = new Request($path, $method, $data, $query, $connection);
 
            $this->_log($request);
 
            $response = $request->send();
 
            $this->_lastRequest = $request;
            $this->_lastResponse = $response;
 
            return $response;
 
        } catch (ConnectionException $e) {
            $connection->setEnabled(false);
 
            // Calls callback with connection as param to make it possible to persist invalid connections
            if ($this->_callback) {
                call_user_func($this->_callback, $connection, $e, $this);
            }
 
            // In case there is no valid connection left, throw exception which caused the disabling of the connection.
            if (!$this->hasConnection())
            {
                throw $e;
            }
            return $this->request($path, $method, $data, $query);
        }
    }
 
    /**
     * Optimizes all search indices
     *
     * @param  array             $args OPTIONAL Optional arguments
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize.html
     */
    public function optimizeAll($args = array())
    {
        return $this->request('_optimize', Request::POST, array(), $args);
    }
 
    /**
     * Refreshes all search indices
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html
     */
    public function refreshAll()
    {
        return $this->request('_refresh', Request::POST);
    }
 
    /**
     * logging
     *
     * @param string|\Elastica\Request $context
     * @throws Exception\RuntimeException
     */
    protected function _log($context)
    {
        $log = $this->getConfig('log');
        if ($log && !class_exists('Psr\Log\AbstractLogger')) {
            throw new RuntimeException('Class Psr\Log\AbstractLogger not found');
        } elseif (!$this->_logger && $log) {
            $this->setLogger(new Log($this->getConfig('log')));
        }
        if ($this->_logger) {
            if ($context instanceof Request) {
                $data = $context->toArray();
            } else {
                $data = array('message' => $context);
            }
            $this->_logger->debug('logging Request', $data);
        }
    }
 
    /**
     * @return \Elastica\Request
     */
    public function getLastRequest()
    {
        return $this->_lastRequest;
    }
 
    /**
     * @return \Elastica\Response
     */
    public function getLastResponse()
    {
        return $this->_lastResponse;
    }
 
    /**
     * set Logger
     *
     * @param LoggerInterface $logger
     * @return $this
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->_logger = $logger;
 
        return $this;
    }
}
#2Elastica\Client->request(torrentino_staging/_search, GET, Array([size] => 0, [aggs] => Array([categories] => Array([terms] => Array())), [query] => Array([match_all] => Object(stdClass))), Array())
<?php
 
namespace Elastica;
 
use Elastica\Exception\InvalidException;
use Elastica\Suggest;
 
/**
 * Elastica search object
 *
 * @category Xodoa
 * @package  Elastica
 * @author   Nicolas Ruflin <spam@ruflin.com>
 */
class Search
{
    /*
     * Options
     */
    const OPTION_SEARCH_TYPE = 'search_type';
    const OPTION_ROUTING = 'routing';
    const OPTION_PREFERENCE = 'preference';
    const OPTION_VERSION = 'version';
    const OPTION_TIMEOUT = 'timeout';
    const OPTION_FROM = 'from';
    const OPTION_SIZE = 'size';
    const OPTION_SCROLL = 'scroll';
    const OPTION_SCROLL_ID = 'scroll_id';
 
    /*
     * Search types
     */
    const OPTION_SEARCH_TYPE_COUNT = 'count';
    const OPTION_SEARCH_TYPE_SCAN = 'scan';
    const OPTION_SEARCH_TYPE_DFS_QUERY_THEN_FETCH = 'dfs_query_then_fetch';
    const OPTION_SEARCH_TYPE_DFS_QUERY_AND_FETCH = 'dfs_query_and_fetch';
    const OPTION_SEARCH_TYPE_QUERY_THEN_FETCH = 'query_then_fetch';
    const OPTION_SEARCH_TYPE_QUERY_AND_FETCH = 'query_and_fetch';
    const OPTION_SEARCH_TYPE_SUGGEST = 'suggest';
    const OPTION_SEARCH_TYPE_SCROLL = 'scroll';
 
    /**
     * Array of indices
     *
     * @var array
     */
    protected $_indices = array();
 
    /**
     * Array of types
     *
     * @var array
     */
    protected $_types = array();
 
    /**
     * @var \Elastica\Query
     */
    protected $_query;
 
    /**
     * @var array
     */
    protected $_options = array();
 
    /**
     * Client object
     *
     * @var \Elastica\Client
     */
    protected $_client;
 
    /**
     * Constructs search object
     *
     * @param \Elastica\Client $client Client object
     */
    public function __construct(Client $client)
    {
        $this->_client = $client;
    }
 
    /**
     * Adds a index to the list
     *
     * @param  \Elastica\Index|string $index Index object or string
     * @throws \Elastica\Exception\InvalidException
     * @return \Elastica\Search                     Current object
     */
    public function addIndex($index)
    {
        if ($index instanceof Index) {
            $index = $index->getName();
        }
 
        if (!is_string($index)) {
            throw new InvalidException('Invalid param type');
        }
 
        $this->_indices[] = $index;
 
        return $this;
    }
 
    /**
     * Add array of indices at once
     *
     * @param  array $indices
     * @return \Elastica\Search
     */
    public function addIndices(array $indices = array())
    {
        foreach ($indices as $index) {
            $this->addIndex($index);
        }
 
        return $this;
    }
 
    /**
     * Adds a type to the current search
     *
     * @param  \Elastica\Type|string $type Type name or object
     * @return \Elastica\Search                     Search object
     * @throws \Elastica\Exception\InvalidException
     */
    public function addType($type)
    {
        if ($type instanceof Type) {
            $type = $type->getName();
        }
 
        if (!is_string($type)) {
            throw new InvalidException('Invalid type type');
        }
 
        $this->_types[] = $type;
 
        return $this;
    }
 
    /**
     * Add array of types
     *
     * @param  array $types
     * @return \Elastica\Search
     */
    public function addTypes(array $types = array())
    {
        foreach ($types as $type) {
            $this->addType($type);
        }
 
        return $this;
    }
 
    /**
     * @param  string|array|\Elastica\Query|\Elastica\Suggest|\Elastica\Query\AbstractQuery|\Elastica\Filter\AbstractFilter $query|
     * @return \Elastica\Search
     */
    public function setQuery($query)
    {
        $this->_query = Query::create($query);
 
        return $this;
    }
 
    /**
     * @param  string $key
     * @param  mixed $value
     * @return \Elastica\Search
     */
    public function setOption($key, $value)
    {
        $this->_validateOption($key);
 
        $this->_options[$key] = $value;
 
        return $this;
    }
 
    /**
     * @param  array $options
     * @return \Elastica\Search
     */
    public function setOptions(array $options)
    {
        $this->clearOptions();
 
        foreach ($options as $key => $value) {
            $this->setOption($key, $value);
        }
 
        return $this;
    }
 
    /**
     * @return \Elastica\Search
     */
    public function clearOptions()
    {
        $this->_options = array();
 
        return $this;
    }
 
    /**
     * @param  string $key
     * @param  mixed $value
     * @return \Elastica\Search
     */
    public function addOption($key, $value)
    {
        $this->_validateOption($key);
 
        if (!isset($this->_options[$key])) {
            $this->_options[$key] = array();
        }
 
        $this->_options[$key][] = $value;
 
        return $this;
    }
 
    /**
     * @param  string $key
     * @return bool
     */
    public function hasOption($key)
    {
        return isset($this->_options[$key]);
    }
 
    /**
     * @param  string $key
     * @return mixed
     * @throws \Elastica\Exception\InvalidException
     */
    public function getOption($key)
    {
        if (!$this->hasOption($key)) {
            throw new InvalidException('Option ' . $key . ' does not exist');
        }
 
        return $this->_options[$key];
    }
 
    /**
     * @return array
     */
    public function getOptions()
    {
        return $this->_options;
    }
 
    /**
     * @param  string $key
     * @return bool
     * @throws \Elastica\Exception\InvalidException
     */
    protected function _validateOption($key)
    {
        switch ($key) {
            case self::OPTION_SEARCH_TYPE:
            case self::OPTION_ROUTING:
            case self::OPTION_PREFERENCE:
            case self::OPTION_VERSION:
            case self::OPTION_TIMEOUT:
            case self::OPTION_FROM:
            case self::OPTION_SIZE:
            case self::OPTION_SCROLL:
            case self::OPTION_SCROLL_ID:
            case self::OPTION_SEARCH_TYPE_SUGGEST:
                return true;
        }
 
        throw new InvalidException('Invalid option ' . $key);
    }
 
    /**
     * Return client object
     *
     * @return \Elastica\Client Client object
     */
    public function getClient()
    {
        return $this->_client;
    }
 
    /**
     * Return array of indices
     *
     * @return array List of index names
     */
    public function getIndices()
    {
        return $this->_indices;
    }
 
    /**
     * @return bool
     */
    public function hasIndices()
    {
        return count($this->_indices) > 0;
    }
 
    /**
     * @param Index|string $index
     * @return bool
     */
    public function hasIndex($index)
    {
        if ($index instanceof Index) {
            $index = $index->getName();
        }
 
        return in_array($index, $this->_indices);
    }
 
    /**
     * Return array of types
     *
     * @return array List of types
     */
    public function getTypes()
    {
        return $this->_types;
    }
 
    /**
     * @return bool
     */
    public function hasTypes()
    {
        return count($this->_types) > 0;
    }
 
    /**
     * @param \Elastica\Type|string $type
     * @return bool
     */
    public function hasType($type)
    {
        if ($type instanceof Type) {
            $type = $type->getName();
        }
 
        return in_array($type, $this->_types);
    }
 
    /**
     * @return \Elastica\Query
     */
    public function getQuery()
    {
        if (null === $this->_query) {
            $this->_query = Query::create('');
        }
 
        return $this->_query;
    }
 
    /**
     * Creates new search object
     *
     * @param  \Elastica\SearchableInterface $searchObject
     * @return \Elastica\Search
     */
    public static function create(SearchableInterface $searchObject)
    {
        return $searchObject->createSearch();
    }
 
    /**
     * Combines indices and types to the search request path
     *
     * @return string Search path
     */
    public function getPath()
    {
        if (isset($this->_options[self::OPTION_SCROLL_ID])) {
            return '_search/scroll';
        }
 
        $indices = $this->getIndices();
 
        $path = '';
        $types = $this->getTypes();
 
        if (empty($indices)) {
            if (!empty($types)) {
                $path .= '_all';
            }
        } else {
            $path .= implode(',', $indices);
        }
 
        if (!empty($types)) {
            $path .= '/' . implode(',', $types);
        }
 
        // Add full path based on indices and types -> could be all
        return $path . '/_search';
    }
 
    /**
     * Search in the set indices, types
     *
     * @param  mixed $query
     * @param  int|array $options OPTIONAL Limit or associative array of options (option=>value)
     * @throws \Elastica\Exception\InvalidException
     * @return \Elastica\ResultSet
     */
    public function search($query = '', $options = null)
    {
        $this->setOptionsAndQuery($options, $query);
 
        $query = $this->getQuery();
        $path = $this->getPath();
 
        $params = $this->getOptions();
 
        // Send scroll_id via raw HTTP body to handle cases of very large (> 4kb) ids.
        if ('_search/scroll' == $path) {
            $data = $params[self::OPTION_SCROLL_ID];
            unset($params[self::OPTION_SCROLL_ID]);
        } else {
            $data = $query->toArray();
        }
 
        $response = $this->getClient()->request(
            $path,
            Request::GET,
            $data,
            $params
        );
 
        return new ResultSet($response, $query);
    }
 
    /**
     *
     * @param mixed $query
     * @param $fullResult (default = false) By default only the total hit count is returned. If set to true, the full ResultSet including facets is returned.
     * @return int|ResultSet
     */
    public function count($query = '', $fullResult = false)
    {
        $this->setOptionsAndQuery(null, $query);
 
        $query = $this->getQuery();
        $path = $this->getPath();
 
        $response = $this->getClient()->request(
            $path,
            Request::GET,
            $query->toArray(),
            array(self::OPTION_SEARCH_TYPE => self::OPTION_SEARCH_TYPE_COUNT)
        );
        $resultSet = new ResultSet($response, $query);
 
        return $fullResult ? $resultSet : $resultSet->getTotalHits();
    }
 
    /**
     * @param  array|int $options
     * @param  string|array|\Elastica\Query $query
     * @return \Elastica\Search
     */
    public function setOptionsAndQuery($options = null, $query = '')
    {
        if ('' != $query) {
            $this->setQuery($query);
        }
 
        if (is_int($options)) {
            $this->getQuery()->setSize($options);
        } elseif (is_array($options)) {
            if (isset($options['limit'])) {
                $this->getQuery()->setSize($options['limit']);
                unset($options['limit']);
            }
            if (isset($options['explain'])) {
                $this->getQuery()->setExplain($options['explain']);
                unset($options['explain']);
            }
            $this->setOptions($options);
        }
 
        return $this;
    }
 
    /**
     * @param Suggest $suggest
     * @return Search
     */
    public function setSuggest(Suggest $suggest)
    {
        return $this->setOptionsAndQuery(array(self::OPTION_SEARCH_TYPE_SUGGEST => 'suggest'), $suggest);
    }
 
    /**
     * Returns the ScanAndScroll Iterator
     *
     * @see Elastica\ScanAndScroll
     * @param string $expiryTime
     * @param int $sizePerShard
     * @return ScanAndScroll
     */
    public function scanAndScroll($expiryTime = '1m', $sizePerShard = 1000) {
        return new ScanAndScroll($this, $expiryTime, $sizePerShard);
    }
}
#3Elastica\Search->search()
<?php
 
namespace Elastica;
 
use Elastica\Exception\InvalidException;
use Elastica\Exception\ResponseException;
use Elastica\Index\Settings as IndexSettings;
use Elastica\Index\Stats as IndexStats;
use Elastica\Index\Status as IndexStatus;
 
/**
 * Elastica index object
 *
 * Handles reads, deletes and configurations of an index
 *
 * @category Xodoa
 * @package  Elastica
 * @author   Nicolas Ruflin <spam@ruflin.com>
 */
class Index implements SearchableInterface
{
    /**
     * Index name
     *
     * @var string Index name
     */
    protected $_name = '';
 
    /**
     * Client object
     *
     * @var \Elastica\Client Client object
     */
    protected $_client = null;
 
    /**
     * Creates a new index object
     *
     * All the communication to and from an index goes of this object
     *
     * @param  \Elastica\Client $client Client object
     * @param  string $name Index name
     * @throws \Elastica\Exception\InvalidException
     */
    public function __construct(Client $client, $name)
    {
        $this->_client = $client;
 
        if (!is_string($name)) {
            throw new InvalidException('Index name should be of type string');
        }
        $this->_name = $name;
    }
 
    /**
     * Returns a type object for the current index with the given name
     *
     * @param  string $type Type name
     * @return \Elastica\Type Type object
     */
    public function getType($type)
    {
        return new Type($this, $type);
    }
 
    /**
     * Returns the current status of the index
     *
     * @return \Elastica\Index\Status Index status
     */
    public function getStatus()
    {
        return new IndexStatus($this);
    }
 
    /**
     * Return Index Stats
     *
     * @return \Elastica\Index\Stats
     */
    public function getStats()
    {
        return new IndexStats($this);
    }
 
    /**
     * Gets all the type mappings for an index.
     *
     * @return array
     */
    public function getMapping()
    {
        $path = '_mapping';
 
        $response = $this->request($path, Request::GET);
        $data = $response->getData();
        
        // Get first entry as if index is an Alias, the name of the mapping is the real name and not alias name
        $mapping = array_shift($data);
        
        if (isset($mapping['mappings'])) {
            return $mapping['mappings'];
        }
 
        return array();
    }
 
    /**
     * Returns the index settings object
     *
     * @return \Elastica\Index\Settings Settings object
     */
    public function getSettings()
    {
        return new IndexSettings($this);
    }
 
    /**
     * Uses _bulk to send documents to the server
     *
     * @param  array|\Elastica\Document[] $docs Array of Elastica\Document
     * @return \Elastica\Bulk\ResponseSet
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function updateDocuments(array $docs)
    {
        foreach ($docs as $doc) {
            $doc->setIndex($this->getName());
        }
 
        return $this->getClient()->updateDocuments($docs);
    }
 
    /**
     * Uses _bulk to send documents to the server
     *
     * @param  array|\Elastica\Document[] $docs Array of Elastica\Document
     * @return \Elastica\Bulk\ResponseSet
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function addDocuments(array $docs)
    {
        foreach ($docs as $doc) {
            $doc->setIndex($this->getName());
        }
 
        return $this->getClient()->addDocuments($docs);
    }
 
    /**
     * Deletes the index
     *
     * @return \Elastica\Response Response object
     */
    public function delete()
    {
        $response = $this->request('', Request::DELETE);
 
        return $response;
    }
 
    /**
     * Uses _bulk to delete documents from the server
     *
     * @param  array|\Elastica\Document[] $docs Array of Elastica\Document
     * @return \Elastica\Bulk\ResponseSet
     * @link http://www.elasticsearch.org/guide/reference/api/bulk.html
     */
    public function deleteDocuments(array $docs)
    {
        foreach ($docs as $doc) {
            $doc->setIndex($this->getName());
        }
 
        return $this->getClient()->deleteDocuments($docs);
    }
 
    /**
     * Optimizes search index
     *
     * Detailed arguments can be found here in the link
     *
     * @param  array $args OPTIONAL Additional arguments
     * @return array Server response
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-optimize.html
     */
    public function optimize($args = array())
    {
        $this->request('_optimize', Request::POST, array(), $args);
    }
 
    /**
     * Refreshes the index
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-refresh.html
     */
    public function refresh()
    {
        return $this->request('_refresh', Request::POST, array());
    }
 
    /**
     * Creates a new index with the given arguments
     *
     * @param array $args OPTIONAL Arguments to use
     * @param bool|array $options OPTIONAL
     *                            bool=> Deletes index first if already exists (default = false).
     *                            array => Associative array of options (option=>value)
     * @throws \Elastica\Exception\InvalidException
     * @throws \Elastica\Exception\ResponseException
     * @return array                                Server response
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-create-index.html
     */
    public function create(array $args = array(), $options = null)
    {
        $path = '';
        $query = array();
 
        if (is_bool($options)) {
            if ($options) {
                try {
                    $this->delete();
                } catch (ResponseException $e) {
                    // Table can't be deleted, because doesn't exist
                }
            }
        } else {
            if (is_array($options)) {
                foreach ($options as $key => $value) {
                    switch ($key) {
                        case 'recreate' :
                            try {
                                $this->delete();
                            } catch (ResponseException $e) {
                                // Table can't be deleted, because doesn't exist
                            }
                            break;
                        case 'routing' :
                            $query = array('routing' => $value);
                            break;
                        default:
                            throw new InvalidException('Invalid option ' . $key);
                            break;
                    }
                }
            }
        }
 
        return $this->request($path, Request::PUT, $args, $query);
    }
 
    /**
     * Checks if the given index is already created
     *
     * @return bool True if index exists
     */
    public function exists()
    {
        $response = $this->getClient()->request($this->getName(), Request::HEAD);
        $info = $response->getTransferInfo();
 
        return (bool)($info['http_code'] == 200);
    }
 
    /**
     * @param  string $query
     * @param  int|array $options
     * @return \Elastica\Search
     */
    public function createSearch($query = '', $options = null)
    {
        $search = new Search($this->getClient());
        $search->addIndex($this);
        $search->setOptionsAndQuery($options, $query);
 
        return $search;
    }
 
    /**
     * Searches in this index
     *
     * @param  string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
     * @param  int|array $options OPTIONAL Limit or associative array of options (option=>value)
     * @return \Elastica\ResultSet          ResultSet with all results inside
     * @see \Elastica\SearchableInterface::search
     */
    public function search($query = '', $options = null)
    {
        $search = $this->createSearch($query, $options);
 
        return $search->search();
    }
 
    /**
     * Counts results of query
     *
     * @param  string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
     * @return int                         number of documents matching the query
     * @see \Elastica\SearchableInterface::count
     */
    public function count($query = '')
    {
        $search = $this->createSearch($query);
 
        return $search->count();
    }
 
    /**
     * Opens an index
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html
     */
    public function open()
    {
        $this->request('_open', Request::POST);
    }
 
    /**
     * Closes the index
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html
     */
    public function close()
    {
        return $this->request('_close', Request::POST);
    }
 
    /**
     * Returns the index name
     *
     * @return string Index name
     */
    public function getName()
    {
        return $this->_name;
    }
 
    /**
     * Returns index client
     *
     * @return \Elastica\Client Index client object
     */
    public function getClient()
    {
        return $this->_client;
    }
 
    /**
     * Adds an alias to the current index
     *
     * @param  string $name Alias name
     * @param  bool $replace OPTIONAL If set, an existing alias will be replaced
     * @return \Elastica\Response Response
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html
     */
    public function addAlias($name, $replace = false)
    {
        $path = '_aliases';
 
        $data = array('actions' => array());
 
        if ($replace) {
            $status = new Status($this->getClient());
            foreach ($status->getIndicesWithAlias($name) as $index) {
                $data['actions'][] = array('remove' => array('index' => $index->getName(), 'alias' => $name));
            }
        }
 
        $data['actions'][] = array('add' => array('index' => $this->getName(), 'alias' => $name));
 
        return $this->getClient()->request($path, Request::POST, $data);
    }
 
    /**
     * Removes an alias pointing to the current index
     *
     * @param  string $name Alias name
     * @return \Elastica\Response Response
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html
     */
    public function removeAlias($name)
    {
        $path = '_aliases';
 
        $data = array('actions' => array(array('remove' => array('index' => $this->getName(), 'alias' => $name))));
 
        return $this->getClient()->request($path, Request::POST, $data);
    }
 
    /**
     * Clears the cache of an index
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-clearcache.html
     */
    public function clearCache()
    {
        $path = '_cache/clear';
        // TODO: add additional cache clean arguments
        return $this->request($path, Request::POST);
    }
 
    /**
     * Flushes the index to storage
     *
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-flush.html
     */
    public function flush($refresh = false)
    {
        $path = '_flush';
        return $this->request($path, Request::POST, array(), array('refresh' => $refresh));
    }
 
    /**
     * Can be used to change settings during runtime. One example is to use
     * if for bulk updating {@link http://www.elasticsearch.org/blog/2011/03/23/update-settings.html}
     *
     * @param  array $data Data array
     * @return \Elastica\Response Response object
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html
     */
    public function setSettings(array $data)
    {
        return $this->request('_settings', Request::PUT, $data);
    }
 
    /**
     * Makes calls to the elasticsearch server based on this index
     *
     * @param  string $path Path to call
     * @param  string $method Rest method to use (GET, POST, DELETE, PUT)
     * @param  array $data OPTIONAL Arguments as array
     * @param  array $query OPTIONAL Query params
     * @return \Elastica\Response Response object
     */
    public function request($path, $method, $data = array(), array $query = array())
    {
        $path = $this->getName() . '/' . $path;
 
        return $this->getClient()->request($path, $method, $data, $query);
    }
 
    /**
     * Analyzes a string
     *
     * Detailed arguments can be found here in the link
     *
     * @param  string $text String to be analyzed
     * @param  array $args OPTIONAL Additional arguments
     * @return array Server response
     * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze.html
     */
    public function analyze($text, $args = array())
    {
        $data = $this->request('_analyze', Request::POST, $text, $args)->getData();
        return $data['tokens'];
    }
}
#4Elastica\Index->search(Object(Elastica\Query))
<?php
 
namespace Widgets {
 
    use Helpers\String;
    use Mytutcodim\Mvc\View\Widget\BaseWidget;
    use ShareModels\TorrentsCategories;
 
    /**
     * Class Menu
     *
     * @package Widget
     */
    class Tagcloud extends BaseWidget
    {
 
        const TAGS_COUNT = 30;
        const WIDHT_COUNT = 6;
 
        /**
         *
         */
        public function init()
        {
 
            //@todo фасеты и агрегаторы выдают различный список тегов
            $tags = $this->getTagsElastica();
 
            $this->setParam('tags', $tags);
        }
 
        /**
         * @return array
         */
        protected function getTags()
        {
 
            /** @var array $activeTags массив активных тегов из текущего адреса (ссылки) */
            $activeTags = isset($this->registry['activeTags']) ? $this->registry['activeTags'] : [];
 
            $activeTagsFliped = array_flip($activeTags);
 
 
            /** @var \Elasticsearch\Client $elasticsearch */
            $elasticsearch = $this->elasticsearch;
 
            // корневые категории
            $rootTags = TorrentsCategories::rootCategories('title', 'lower');
 
            // корневые теги выпилятся, поэтому увеличиваем общее число на их количество
            $cloudSize = self::TAGS_COUNT + count($rootTags);
 
            $params = [];
 
            $params['index'] = $this->config->elasticsearch->index;
            $params['type']  = $this->config->elasticsearch->type;
 
            // нам нужны только данные по фасетам, сама выдача в 0
            $params['body']['size'] = 0;
 
            $q = $this->dispatcher->getParam('q', 'string', false);
            $q = String::clean($q);
 
 
            if ($q) {
                $params['body']['query']['bool']['must'][] = [
                    'simple_query_string' => [
                        'fields'           => ['title'],
                        'query'            => $q,
                        'default_operator' => 'and'
                    ]
                ];
            }
 
            // добавляем фильтр по активным тегам
            foreach ($activeTagsFliped as $activeTag => $v) {
 
                // поиск, оно медленее, но работает...
                $params['body']['query']['bool']['must'][]['term']['categories.title'] = $activeTag;
 
                // фильтры, оно быстрее и кеш
                //$params['body']['query']['filtered']['filter']['and'][]['term']['categories.title']
                //= $activeTag;
            }
 
 
            // настройка фасетов (группировок) тегов
 
            $params['body']['facets']['categories']['terms'] = [
                'field' => 'categories.title',
                'size'  => $cloudSize,
                'order' => 'count'
            ];
 
            $tags = $elasticsearch->search($params)['facets']['categories']['terms'];
 
            // если облако оказалось пустым - значит оно должно быть полным
            if (count($tags) == 0) {
 
                unset($params['body']['query']);
 
                $params['body']['facets']['categories']['terms'] = [
                    'field' => 'categories.title',
                    'size'  => $cloudSize,
                    'order' => 'count'
                ];
 
                $tags = $elasticsearch->search($params)['facets']['categories']['terms'];
            }
 
            $routeName        = $this->getActiveRouteName();
            $dispatcherParams = $this->dispatcher->getParams();
 
 
            // мы в категории, как активный тег нам название категории не нужно
            if ($routeName == 'torrent-cat-tags') {
 
                $activeCategory = $this->registry['activeCategory'];
                $cleanTagsArray = $activeTagsFliped;
 
                // удаляем текущую (активную) категорию из общего спивка тегов в ссылках
                unset($cleanTagsArray[$activeCategory]);
 
                $activeTags = array_flip($cleanTagsArray);
            }
 
            if ($routeName == 'search-index') {
 
                $q = $this->dispatcher->getParam('q', 'string', false);
                $q = String::clean($q);
            }
 
            $result = [];
            $n      = 1;
 
            // расчитываем максимальный вес и число шагов для его уменьшения
            $step = round(self::TAGS_COUNT / self::WIDHT_COUNT);
 
            $weight = 1;
 
            foreach ($tags as $tag) {
 
                // пропускаем корневые категории
                if (isset($rootTags[$tag['term']])) {
                    continue;
                }
 
                // мигрируем уже активные теги и новый, для текущей ссылки
                $tagsArray = $activeTags;
                array_push($tagsArray, $tag['term']);
                $tagsArray = array_unique($tagsArray);
 
                $activeTag = isset($activeTagsFliped[$tag['term']]) ? true : false;
 
                // у активного тега делаем удаление его из тегов своей ссылки (второй клик по тегу - для исключения)
                if ($activeTag) {
                    $tagsArray = array_diff($tagsArray, [$tag['term']]);
                }
 
                if ($routeName == 'search-index') {
 
                    $tagUrl = $this->url->get(
                        [
                            'for' => $routeName,
                            'q'   => $q
                        ] + $dispatcherParams,
                        ($tagsArray ? ['tags' => implode(',', $tagsArray)] : null)
                    );
                } else {
                    $tagUrl = $this->url->get(
                        [
                            'for'        => $routeName,
                            'sortable'   => 'tags_array',
                            'tags_array' => $tagsArray,
                        ] + $dispatcherParams
                    );
                }
 
                $result[] = [
                    'weight' => $weight,
                    'title'  => $tag['term'],
                    'href'   => $tagUrl,
                    'active' => $activeTag
                ];
 
                if ($n == $step) {
 
                    ++$weight;
                    $n = 0;
                }
 
                ++$n;
            }
 
            // сортируем по алфавиту для столбца title
            usort(
                $result,
                function ($a, $b) {
                    if ($a['title'] == $b['title']) {
                        return 0;
                    }
                    return ($a['title'] < $b['title']) ? -1 : 1;
                }
            );
 
            return $result;
        }
 
        protected function getTagsElastica()
        {
            /** @var array $activeTags массив активных тегов из текущего адреса (ссылки) */
            $activeTags = isset($this->registry['activeTags']) ? $this->registry['activeTags'] : [];
 
            $activeTagsFliped = array_flip($activeTags);
 
 
            /* @var $index \Elastica\Index */
            $index = $this->di->get('elastica')['index'];
 
            // корневые категории
            $rootTags = TorrentsCategories::rootCategories('title', 'lower');
 
            // корневые теги выпилятся, поэтому увеличиваем общее число на их количество
            $cloudSize = self::TAGS_COUNT + count($rootTags);
 
            $query = new \Elastica\Query();
 
            // нам нужны только данные по фасетам, сама выдача в 0
            $query->setSize(0);
 
            $q = $this->dispatcher->getParam('q', 'string', false);
            $q = String::clean($q);
 
            $bool = new \Elastica\Query\Bool();
 
            if ($q) {
 
                $simpleQueryString = new \Elastica\Query\SimpleQueryString($q, ['title']);
                $simpleQueryString->setDefaultOperator('and');
 
                $bool->addMust($simpleQueryString);
            }
 
            // добавляем фильтр по активным тегам
            foreach ($activeTagsFliped as $activeTag => $v) {
 
                // поиск, оно медленее, но работает...
                $term = new \Elastica\Query\Term(['categories.title' => $activeTag]);
                $bool->addMust($term);
 
                // фильтры, оно быстрее и кеш
            }
 
            $termsAgg = new \Elastica\Aggregation\Terms('categories');
            $termsAgg->setField('categories.title');
            $termsAgg->setSize($cloudSize);
 
            if (count($bool->getParams()) != 0) {
 
                $query->setQuery($bool);
            }
 
            $query->addAggregation($termsAgg);
 
            $resultSet = $index->search($query);
 
            $tags = $resultSet->getAggregation('categories')['buckets'];
 
            // если облако оказалось пустым - значит оно должно быть полным
            if (count($tags) == 0) {
 
                $query = new \Elastica\Query();
 
                $query->addAggregation($termsAgg);
 
                $resultSet = $index->search($query);
 
                $tags = $resultSet->getAggregation('categories')['buckets'];
            }
 
            $routeName        = $this->getActiveRouteName();
            $dispatcherParams = $this->dispatcher->getParams();
 
 
            // мы в категории, как активный тег нам название категории не нужно
            if ($routeName == 'torrent-cat-tags') {
 
                $activeCategory = $this->registry['activeCategory'];
                $cleanTagsArray = $activeTagsFliped;
 
                // удаляем текущую (активную) категорию из общего спивка тегов в ссылках
                unset($cleanTagsArray[$activeCategory]);
 
                $activeTags = array_flip($cleanTagsArray);
            }
 
            if ($routeName == 'search-index') {
 
                $q = $this->dispatcher->getParam('q', 'string', false);
                $q = String::clean($q);
            }
 
            $result = [];
            $n      = 1;
 
            // расчитываем максимальный вес и число шагов для его уменьшения
            $step = round(self::TAGS_COUNT / self::WIDHT_COUNT);
 
            $weight = 1;
 
            foreach ($tags as $tag) {
 
                // пропускаем корневые категории
                if (isset($rootTags[$tag['key']])) {
                    continue;
                }
 
                // мигрируем уже активные теги и новый, для текущей ссылки
                $tagsArray = $activeTags;
                array_push($tagsArray, $tag['key']);
                $tagsArray = array_unique($tagsArray);
 
                $activeTag = isset($activeTagsFliped[$tag['key']]) ? true : false;
 
                // у активного тега делаем удаление его из тегов своей ссылки (второй клик по тегу - для исключения)
                if ($activeTag) {
                    $tagsArray = array_diff($tagsArray, [$tag['key']]);
                }
 
                if ($routeName == 'search-index') {
 
                    $tagUrl = $this->url->get(
                        [
                            'for' => $routeName,
                            'q'   => $q
                        ] + $dispatcherParams,
                        ($tagsArray ? ['tags' => implode(',', $tagsArray)] : null)
                    );
                } else {
                    $tagUrl = $this->url->get(
                        [
                            'for'        => $routeName,
                            'sortable'   => 'tags_array',
                            'tags_array' => $tagsArray,
                        ] + $dispatcherParams
                    );
                }
 
                $result[] = [
                    'weight' => $weight,
                    'title'  => $tag['key'],
                    'href'   => $tagUrl,
                    'active' => $activeTag
                ];
 
                if ($n == $step) {
 
                    ++$weight;
                    $n = 0;
                }
 
                ++$n;
            }
 
            // сортируем по алфавиту для столбца title
            usort(
                $result,
                function ($a, $b) {
                    if ($a['title'] == $b['title']) {
                        return 0;
                    }
                    return ($a['title'] < $b['title']) ? -1 : 1;
                }
            );
 
            return $result;
        }
 
        /**
         * Получение названия текущего правила роутинга
         *
         * @return string
         */
        protected function getActiveRouteName()
        {
 
            /** @var string $previousAction категории и поиск выводятся через один action, но для категорий он первый */
            $previousAction = $this->dispatcher->getPreviousActionName();
 
            /** @var string $actionName , а вот для тегов он единственный, и предыдущий это NULL */
            $actionName = $previousAction == null ? $this->dispatcher->getActionName() : $previousAction;
 
            $previousController = $this->dispatcher->getPreviousControllerName();
            $controllerName
                                =
                $previousController == null ? $this->dispatcher->getControllerName() : $previousController;
 
            switch ($actionName) {
 
 
                case 'index':
                case 'tags':
                default:
                    $routeName = 'search-tags';
                    break;
 
                case 'category':
                    $routeName = 'torrent-cat-tags';
                    break;
            }
 
            if ($controllerName == 'Search' && $actionName == 'index') {
                $routeName = 'search-index';
            }
 
            return $routeName;
        }
    }
}
#5Widgets\Tagcloud->getTagsElastica()
<?php
 
namespace Widgets {
 
    use Helpers\String;
    use Mytutcodim\Mvc\View\Widget\BaseWidget;
    use ShareModels\TorrentsCategories;
 
    /**
     * Class Menu
     *
     * @package Widget
     */
    class Tagcloud extends BaseWidget
    {
 
        const TAGS_COUNT = 30;
        const WIDHT_COUNT = 6;
 
        /**
         *
         */
        public function init()
        {
 
            //@todo фасеты и агрегаторы выдают различный список тегов
            $tags = $this->getTagsElastica();
 
            $this->setParam('tags', $tags);
        }
 
        /**
         * @return array
         */
        protected function getTags()
        {
 
            /** @var array $activeTags массив активных тегов из текущего адреса (ссылки) */
            $activeTags = isset($this->registry['activeTags']) ? $this->registry['activeTags'] : [];
 
            $activeTagsFliped = array_flip($activeTags);
 
 
            /** @var \Elasticsearch\Client $elasticsearch */
            $elasticsearch = $this->elasticsearch;
 
            // корневые категории
            $rootTags = TorrentsCategories::rootCategories('title', 'lower');
 
            // корневые теги выпилятся, поэтому увеличиваем общее число на их количество
            $cloudSize = self::TAGS_COUNT + count($rootTags);
 
            $params = [];
 
            $params['index'] = $this->config->elasticsearch->index;
            $params['type']  = $this->config->elasticsearch->type;
 
            // нам нужны только данные по фасетам, сама выдача в 0
            $params['body']['size'] = 0;
 
            $q = $this->dispatcher->getParam('q', 'string', false);
            $q = String::clean($q);
 
 
            if ($q) {
                $params['body']['query']['bool']['must'][] = [
                    'simple_query_string' => [
                        'fields'           => ['title'],
                        'query'            => $q,
                        'default_operator' => 'and'
                    ]
                ];
            }
 
            // добавляем фильтр по активным тегам
            foreach ($activeTagsFliped as $activeTag => $v) {
 
                // поиск, оно медленее, но работает...
                $params['body']['query']['bool']['must'][]['term']['categories.title'] = $activeTag;
 
                // фильтры, оно быстрее и кеш
                //$params['body']['query']['filtered']['filter']['and'][]['term']['categories.title']
                //= $activeTag;
            }
 
 
            // настройка фасетов (группировок) тегов
 
            $params['body']['facets']['categories']['terms'] = [
                'field' => 'categories.title',
                'size'  => $cloudSize,
                'order' => 'count'
            ];
 
            $tags = $elasticsearch->search($params)['facets']['categories']['terms'];
 
            // если облако оказалось пустым - значит оно должно быть полным
            if (count($tags) == 0) {
 
                unset($params['body']['query']);
 
                $params['body']['facets']['categories']['terms'] = [
                    'field' => 'categories.title',
                    'size'  => $cloudSize,
                    'order' => 'count'
                ];
 
                $tags = $elasticsearch->search($params)['facets']['categories']['terms'];
            }
 
            $routeName        = $this->getActiveRouteName();
            $dispatcherParams = $this->dispatcher->getParams();
 
 
            // мы в категории, как активный тег нам название категории не нужно
            if ($routeName == 'torrent-cat-tags') {
 
                $activeCategory = $this->registry['activeCategory'];
                $cleanTagsArray = $activeTagsFliped;
 
                // удаляем текущую (активную) категорию из общего спивка тегов в ссылках
                unset($cleanTagsArray[$activeCategory]);
 
                $activeTags = array_flip($cleanTagsArray);
            }
 
            if ($routeName == 'search-index') {
 
                $q = $this->dispatcher->getParam('q', 'string', false);
                $q = String::clean($q);
            }
 
            $result = [];
            $n      = 1;
 
            // расчитываем максимальный вес и число шагов для его уменьшения
            $step = round(self::TAGS_COUNT / self::WIDHT_COUNT);
 
            $weight = 1;
 
            foreach ($tags as $tag) {
 
                // пропускаем корневые категории
                if (isset($rootTags[$tag['term']])) {
                    continue;
                }
 
                // мигрируем уже активные теги и новый, для текущей ссылки
                $tagsArray = $activeTags;
                array_push($tagsArray, $tag['term']);
                $tagsArray = array_unique($tagsArray);
 
                $activeTag = isset($activeTagsFliped[$tag['term']]) ? true : false;
 
                // у активного тега делаем удаление его из тегов своей ссылки (второй клик по тегу - для исключения)
                if ($activeTag) {
                    $tagsArray = array_diff($tagsArray, [$tag['term']]);
                }
 
                if ($routeName == 'search-index') {
 
                    $tagUrl = $this->url->get(
                        [
                            'for' => $routeName,
                            'q'   => $q
                        ] + $dispatcherParams,
                        ($tagsArray ? ['tags' => implode(',', $tagsArray)] : null)
                    );
                } else {
                    $tagUrl = $this->url->get(
                        [
                            'for'        => $routeName,
                            'sortable'   => 'tags_array',
                            'tags_array' => $tagsArray,
                        ] + $dispatcherParams
                    );
                }
 
                $result[] = [
                    'weight' => $weight,
                    'title'  => $tag['term'],
                    'href'   => $tagUrl,
                    'active' => $activeTag
                ];
 
                if ($n == $step) {
 
                    ++$weight;
                    $n = 0;
                }
 
                ++$n;
            }
 
            // сортируем по алфавиту для столбца title
            usort(
                $result,
                function ($a, $b) {
                    if ($a['title'] == $b['title']) {
                        return 0;
                    }
                    return ($a['title'] < $b['title']) ? -1 : 1;
                }
            );
 
            return $result;
        }
 
        protected function getTagsElastica()
        {
            /** @var array $activeTags массив активных тегов из текущего адреса (ссылки) */
            $activeTags = isset($this->registry['activeTags']) ? $this->registry['activeTags'] : [];
 
            $activeTagsFliped = array_flip($activeTags);
 
 
            /* @var $index \Elastica\Index */
            $index = $this->di->get('elastica')['index'];
 
            // корневые категории
            $rootTags = TorrentsCategories::rootCategories('title', 'lower');
 
            // корневые теги выпилятся, поэтому увеличиваем общее число на их количество
            $cloudSize = self::TAGS_COUNT + count($rootTags);
 
            $query = new \Elastica\Query();
 
            // нам нужны только данные по фасетам, сама выдача в 0
            $query->setSize(0);
 
            $q = $this->dispatcher->getParam('q', 'string', false);
            $q = String::clean($q);
 
            $bool = new \Elastica\Query\Bool();
 
            if ($q) {
 
                $simpleQueryString = new \Elastica\Query\SimpleQueryString($q, ['title']);
                $simpleQueryString->setDefaultOperator('and');
 
                $bool->addMust($simpleQueryString);
            }
 
            // добавляем фильтр по активным тегам
            foreach ($activeTagsFliped as $activeTag => $v) {
 
                // поиск, оно медленее, но работает...
                $term = new \Elastica\Query\Term(['categories.title' => $activeTag]);
                $bool->addMust($term);
 
                // фильтры, оно быстрее и кеш
            }
 
            $termsAgg = new \Elastica\Aggregation\Terms('categories');
            $termsAgg->setField('categories.title');
            $termsAgg->setSize($cloudSize);
 
            if (count($bool->getParams()) != 0) {
 
                $query->setQuery($bool);
            }
 
            $query->addAggregation($termsAgg);
 
            $resultSet = $index->search($query);
 
            $tags = $resultSet->getAggregation('categories')['buckets'];
 
            // если облако оказалось пустым - значит оно должно быть полным
            if (count($tags) == 0) {
 
                $query = new \Elastica\Query();
 
                $query->addAggregation($termsAgg);
 
                $resultSet = $index->search($query);
 
                $tags = $resultSet->getAggregation('categories')['buckets'];
            }
 
            $routeName        = $this->getActiveRouteName();
            $dispatcherParams = $this->dispatcher->getParams();
 
 
            // мы в категории, как активный тег нам название категории не нужно
            if ($routeName == 'torrent-cat-tags') {
 
                $activeCategory = $this->registry['activeCategory'];
                $cleanTagsArray = $activeTagsFliped;
 
                // удаляем текущую (активную) категорию из общего спивка тегов в ссылках
                unset($cleanTagsArray[$activeCategory]);
 
                $activeTags = array_flip($cleanTagsArray);
            }
 
            if ($routeName == 'search-index') {
 
                $q = $this->dispatcher->getParam('q', 'string', false);
                $q = String::clean($q);
            }
 
            $result = [];
            $n      = 1;
 
            // расчитываем максимальный вес и число шагов для его уменьшения
            $step = round(self::TAGS_COUNT / self::WIDHT_COUNT);
 
            $weight = 1;
 
            foreach ($tags as $tag) {
 
                // пропускаем корневые категории
                if (isset($rootTags[$tag['key']])) {
                    continue;
                }
 
                // мигрируем уже активные теги и новый, для текущей ссылки
                $tagsArray = $activeTags;
                array_push($tagsArray, $tag['key']);
                $tagsArray = array_unique($tagsArray);
 
                $activeTag = isset($activeTagsFliped[$tag['key']]) ? true : false;
 
                // у активного тега делаем удаление его из тегов своей ссылки (второй клик по тегу - для исключения)
                if ($activeTag) {
                    $tagsArray = array_diff($tagsArray, [$tag['key']]);
                }
 
                if ($routeName == 'search-index') {
 
                    $tagUrl = $this->url->get(
                        [
                            'for' => $routeName,
                            'q'   => $q
                        ] + $dispatcherParams,
                        ($tagsArray ? ['tags' => implode(',', $tagsArray)] : null)
                    );
                } else {
                    $tagUrl = $this->url->get(
                        [
                            'for'        => $routeName,
                            'sortable'   => 'tags_array',
                            'tags_array' => $tagsArray,
                        ] + $dispatcherParams
                    );
                }
 
                $result[] = [
                    'weight' => $weight,
                    'title'  => $tag['key'],
                    'href'   => $tagUrl,
                    'active' => $activeTag
                ];
 
                if ($n == $step) {
 
                    ++$weight;
                    $n = 0;
                }
 
                ++$n;
            }
 
            // сортируем по алфавиту для столбца title
            usort(
                $result,
                function ($a, $b) {
                    if ($a['title'] == $b['title']) {
                        return 0;
                    }
                    return ($a['title'] < $b['title']) ? -1 : 1;
                }
            );
 
            return $result;
        }
 
        /**
         * Получение названия текущего правила роутинга
         *
         * @return string
         */
        protected function getActiveRouteName()
        {
 
            /** @var string $previousAction категории и поиск выводятся через один action, но для категорий он первый */
            $previousAction = $this->dispatcher->getPreviousActionName();
 
            /** @var string $actionName , а вот для тегов он единственный, и предыдущий это NULL */
            $actionName = $previousAction == null ? $this->dispatcher->getActionName() : $previousAction;
 
            $previousController = $this->dispatcher->getPreviousControllerName();
            $controllerName
                                =
                $previousController == null ? $this->dispatcher->getControllerName() : $previousController;
 
            switch ($actionName) {
 
 
                case 'index':
                case 'tags':
                default:
                    $routeName = 'search-tags';
                    break;
 
                case 'category':
                    $routeName = 'torrent-cat-tags';
                    break;
            }
 
            if ($controllerName == 'Search' && $actionName == 'index') {
                $routeName = 'search-index';
            }
 
            return $routeName;
        }
    }
}
#6Widgets\Tagcloud->init()
<?php
 
namespace Mytutcodim\Mvc\View {
 
    use Mytutcodim\Mvc\View\Widget\BaseWidget;
    use Phalcon\Mvc\User\Component;
    use Phalcon\Mvc\View\Exception as ViewException;
 
    /**
     * Class Widget
     *
     * @property \Phalcon\Mvc\View\Simple widgetRender
     *
     * @package Mytutcodim\Mvc\View
     */
    class Widget extends Component
    {
 
        /**
         * @var BaseWidget
         */
        protected $wingetClass;
 
 
        /**
         * @param       $name
         * @param array $params
         *
         * @throws ViewException
         */
        public function __construct($name, array $params = [])
        {
 
            $widgetClass = '\Widgets\\' . $name;
 
            if (!class_exists($widgetClass)) {
 
                throw new ViewException('Widget class: ' . $widgetClass . ' not found');
            }
 
            /** @var BaseWidget wingetClass */
            $this->wingetClass = new $widgetClass;
            $this->wingetClass->init();
            $this->wingetClass->setParams($params);
            $this->wingetClass->setViewTemplate($name);
        }
 
        /**
         * @return string
         */
        public function render()
        {
            return $this->wingetClass->run();
        }
 
        /**
         * @return string
         */
        public function __toString()
        {
            try {
                $content = $this->render();
 
                if (empty($content)) {
                    if (APPLICATION_ENV == 'development') {
 
                        throw new ViewException('Содержимое виджета отсутствует, проверьте метод Winget::run');
                    }
                }
            } catch (ViewException $e) {
                $content = $e->getMessage();
            } catch (\Exception $e) {
                $content = $e->getMessage();
            }
            return $content;
        }
    }
}
#7Mytutcodim\Mvc\View\Widget->__construct(Tagcloud, Array())
<?php
 
namespace Mytutcodim\Mvc\View\Engine {
 
    use Mytutcodim\Mvc\View\Widget;
    use Phalcon\Mvc\View\Engine\Php;
 
    /**
     * Class Fly
     *
     * @package Mytutcodim\Mvc\View\Engine
     */
    class Fly extends Php
    {
 
        /**
         * @param       $name
         * @param array $params
         *
         * @return Widget
         */
        public function widget($name, $params = [])
        {
            return new Widget($name, $params);
        }
    }
}
#8Mytutcodim\Mvc\View\Engine\Fly->widget(Tagcloud)
<?php
/**
 * @var \Phalcon\Mvc\View\Engine\Php $this
 * @var array $torrent
 */
 
$abuzed = $torrent['abused'];
 
?>
<link rel="stylesheet" href="/<?= (APPLICATION_ENV != 'development') ? 'build' : 'dev'; ?>/css/torrent.css<?= (APPLICATION_ENV != 'development' ? ('?'.$build_version) : '?t='.time())?>">
<script>
    var abuzed = <?php echo ($abuzed) ? 'true' : 'false' ?>;
</script>
 
<?php if ($abuzed) :
    $this->partial("abuzed");
else:
    $download_proxy = $this->config->downloads->type;
    $timeout        = $this->config->downloads->timeout;
    $this->partial("download-controls/".$download_proxy, ['timeout'=> $timeout ]);
endif ?>
 
<aside class="right">
    <?php if (APPLICATION_ENV != 'development') { ?>
        <?php $this->partial("banners/right") ?>
    <?php } ?>
 
</aside>
<aside class="left">
    <?= $this->widget('NewTorrents'); ?>
</aside>
<section class="m-left m-right">
    <?php $this->partial("search-bar") ?>
    <div class="plate torrent">
        <div class="head">
            <h1 class="module-header"><?php echo $torrent['title'] ?></h1>
        </div>
        <div class="categories">
            <?php
            $categories = $torrent['categories'];
            $countCategories = count($categories);
            for ($i = 0; $i < $countCategories; $i++) {
                $category = $categories[$i];
                $href     = $this->url->get(['for' => 'search-tags', 'tags_array' => $category['title']]);
                echo '<a title="Искать торренты с тегом '.$categories[$i]['title'].'" '. (($i == 0) ? 'class="first"' : '') .' href="'.$href.'">' . $categories[$i]['title'] . '</a>' . (($i + 1 != $countCategories) ? ', ' : '');
            }
            ?>
        </div>
        <div class="controls">
            <?php if($abuzed != true):?>
                <a title="Скачать торрент <?php echo $torrent['title'];?>" href="javascript:void(0);" class="button middle rounded download">Скачать торрент · <?php echo $torrent['size'];?></a>
            <?php else: ?>
                <a title="Скачивание торрента запрещено" href="javascript:void(0);" class="button middle rounded download restricted">Скачивание торрента запрещено</a>
            <?php endif ?>
            <div class="stats">
                <table>
                    <tr class="label">
                        <td>Сиды </td>
                        <td>&nbsp;/&nbsp;</td>
                        <td>Личи</td>
                    </tr>
                    <tr>
                        <td class="seed"><?= $torrent["seed_leech"]["seed"] ?></td>
                        <td>&nbsp;/&nbsp;</td>
                        <td class="leech"><?= $torrent["seed_leech"]["leech"] ?></td>
                    </tr>
                </table>
            </div>
        </div>
        <div class="info">
            <?php if (isset($torrent['covers']['thumb'])){ ?>
                <div class="cover">
                    <img width="210px" height="293px" class="roundy" src="<?= $torrent['covers']['thumb'] ?>" />
                </div>
                <div class="description m-left">
            <?php } else { ?>
                <div class="description">
            <?php }?>
                    <?php echo nl2br($torrent['description']); ?>
                </div>
            </div>
            <?php if (!empty($torrent['screenshots'])){ ?>
                <div class="screenshots">
                    <ul>
                        <?php
                            $screenshots = $torrent['screenshots'];
                            for ($j = 0 ; $j < count($screenshots); $j++) {
                                echo '<li><img src="'.$screenshots[$j]['thumb'].'"></li> ';
                            }
                        ?>
                    </ul>
                </div>
            <?php } ?>
        </div>
        <?php if (APPLICATION_ENV != 'development') { ?>
            <div class="plate transparently">
                <?php $this->partial("banners/4") ?>
            </div>
        <?php } ?>
 
            <?= $this->widget('Same', ['torrent' => $torrent]) ?>
 
        <?php if (APPLICATION_ENV != 'development') { ?>
            <?php $this->partial("banners/2") ?>
        <?php } ?>
        <div class="plate tag-plate transparently">
            <?= $this->widget('Tagcloud'); ?>
        </div>
    </div>
</section>
#9Phalcon\Mvc\View\Engine\Php->render(/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Torrents/view.phtml, Array([build_version] => 1.0.10, [torrent] => Array(19)), true)
#10Phalcon\Mvc\View->_engineRender(Array([.phtml] => Object(Mytutcodim\Mvc\View\Engine\Fly)), Torrents/view, true, true, null)
#11Phalcon\Mvc\View->render(Torrents, view, Array([id] => aoep, [slug] => medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes))
#12Phalcon\Mvc\Application->handle()
<?php
 
require_once __DIR__ . '/../app/config/constants.php';
require_once APPLICATION_ROOT_CORE . '/vendor/autoload.php';
 
$config = require_once APPLICATION_ROOT . '/config/config.php';
 
require APPLICATION_ROOT . '/config/loader.php';
 
require APPLICATION_ROOT . '/config/services.php';
 
require APPLICATION_ROOT . '/Application.php';
 
$application = (new Flycon\Application($di));
$application->registerModules(require APPLICATION_ROOT . '/config/modules.php');
 
echo $application->handle()->getContent();
KeyValue
_url/torrents/aoep-medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes
KeyValue
REDIRECT_STATUS200
HTTP_HOSTwww.torrentino.ru
HTTP_X_FORWARDED_FOR217.118.93.112
HTTP_X_REAL_IP217.118.93.112
HTTP_CONNECTIONclose
HTTP_ACCEPTtext/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
HTTP_ACCEPT_ENCODINGgzip,deflate,sdch
HTTP_ACCEPT_LANGUAGEru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
HTTP_REFERERhttp://go.mail.ru/search?q=%D1%81%D0%BA%D0%B0%D1%87%D0%B0%D1%82%D1%8C+stainless+steel+6.4&us=17&usln=5&usstr=stainless+steel+6
HTTP_USER_AGENTMozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.75 Safari/537.36 MRCHROME
PATH/sbin:/usr/sbin:/bin:/usr/bin
SERVER_SIGNATURE<address>Apache/2.2.15 (CentOS) Server at www.torrentino.ru Port 80</address>\n
SERVER_SOFTWAREApache/2.2.15 (CentOS)
SERVER_NAMEwww.torrentino.ru
SERVER_ADDR127.0.0.1
SERVER_PORT80
REMOTE_ADDR217.118.93.112
DOCUMENT_ROOT/var/www/vhosts/torrentino/torrentino.ru/www
SERVER_ADMINsupport@support.ru
SCRIPT_FILENAME/var/www/vhosts/torrentino/torrentino.ru/www/index.php
REMOTE_PORT36657
REDIRECT_QUERY_STRING_url=/torrents/aoep-medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes
REDIRECT_URL/torrents/aoep-medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes
GATEWAY_INTERFACECGI/1.1
SERVER_PROTOCOLHTTP/1.0
REQUEST_METHODGET
QUERY_STRING_url=/torrents/aoep-medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes
REQUEST_URI/torrents/aoep-medieval-ii-total-war-kingdoms-mod-stainless-steel-6-4-fixes
SCRIPT_NAME/index.php
PHP_SELF/index.php
REQUEST_TIME_FLOAT1406898156.968
REQUEST_TIME1406898156
#Path
0/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/public/index.php
1/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/constants.php
2/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/autoload.php
3/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/composer/autoload_real.php
4/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/composer/ClassLoader.php
5/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/composer/autoload_namespaces.php
6/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/composer/autoload_psr4.php
7/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/composer/autoload_classmap.php
8/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/config.production.php
9/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/loader.php
10/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/services.php
11/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Application.php
12/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/modules.php
13/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/config/routes.php
14/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Index/Config/Routes.php
15/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Torrents/Config/Routes.php
16/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Search/Config/Routes.php
17/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/ShareModels/TorrentsCategories.php
18/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/ShareModels/BaseModel.php
19/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/Model/Behavior/Seomonster.php
20/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Pages/Config/Routes.php
21/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Rewrite/Config/Routes.php
22/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Backend/Config/Routes.php
23/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Api/Config/Routes.php
24/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Tests/Config/Routes.php
25/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Torrents/Module.php
26/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/User/Plugin/DispatcherTags.php
27/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/User/Plugin/SeoMonster.php
28/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/User/Component/Seomonster.php
29/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/ShareModels/SeomonsterRules.php
30/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/ShareModels/SeomonsterTitles.php
31/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Torrents/Controllers/TorrentsController.php
32/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Modules/Torrents/Controllers/BaseController.php
33/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Helpers/Torrent.php
34/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Services/Torrents.php
35/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Services/TorrentProviders/Elasticsearch/BaseProvider.php
36/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Services/TorrentProviders/TorrentProviderInterface.php
37/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Client.php
38/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Connection.php
39/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Param.php
40/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Index.php
41/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/SearchableInterface.php
42/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Type.php
43/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Request.php
44/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Transport/AbstractTransport.php
45/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Transport/Http.php
46/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Util.php
47/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Response.php
48/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/JSON.php
49/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Exception/NotFoundException.php
50/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Exception/ExceptionInterface.php
51/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Document.php
52/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/AbstractUpdateAction.php
53/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Bulk/Action.php
54/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/Url/SortUrl.php
55/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/View/Engine/Fly.php
56/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Torrents/view.phtml
57/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Partials/download-controls/zona.phtml
58/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/View/Widget.php
59/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Widgets/NewTorrents.php
60/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Mytutcodim/Mvc/View/Widget/BaseWidget.php
61/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Widgets/NewTorrents.phtml
62/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Partials/list/list.phtml
63/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Partials/list/types/new.phtml
64/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Views/Partials/search-bar.phtml
65/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Widgets/Same.php
66/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Services/TorrentProviders/Elasticsearch/SimilarsByTorrent.php
67/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Query/SimpleQueryString.php
68/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Query/AbstractQuery.php
69/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Filter/Term.php
70/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Filter/AbstractFilter.php
71/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Filter/BoolNot.php
72/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Query.php
73/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Search.php
74/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Exception/ResponseException.php
75/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Widgets/Tagcloud.php
76/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/app/Library/Helpers/String.php
77/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Query/Bool.php
78/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Aggregation/Terms.php
79/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractSimpleAggregation.php
80/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Aggregation/AbstractAggregation.php
81/var/www/vhosts/torrentino/torrentino.ru/repos/releases/20140801105914/vendor/ruflin/elastica/lib/Elastica/Query/MatchAll.php
Memory
Usage1835008