<?php

namespace DruidFamiliar\ExampleGroupByQueries;

use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Exception;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;

class ReferralsByCompanyGroupByQueryGenerator implements IDruidQueryGenerator
{

    /**
     * As opposed to building the query body in PHP associative arrays, one could also template them.
     *
     * @var string
     */
    private $queryTemplate = <<<QUERYTEMPLATE
{
    "queryType": "groupBy",
    "dataSource": "{DATASOURCE}",
    "granularity": { "type": "period", "period": "P3M"},
    "dimensions": ["company_id", "facility_id", "referral_count"],
    "aggregations": [
        {"type": "count", "name": "total_entries"},
        {"type": "longSum", "name": "total_referral_countb", "fieldName": "referral_count"}
    ],
    "intervals": ["{STARTINTERVAL}/{ENDINTERVAL}"]
}
QUERYTEMPLATE;

    /**
     * Take parameters and return a valid Druid Query.
     *
     * @param ReferralsByCompanyGroupByQueryParameters $params
     * @return string Query payload in JSON
     */
    public function generateQuery(IDruidQueryParameters $params)
    {
        // @var ReferralsByCompanyGroupByQueryParameters $params
        $query = $this->queryTemplate;

        $query = str_replace('{DATASOURCE}',    $params->dataSource,    $query);
        $query = str_replace('{STARTINTERVAL}', $params->startInterval, $query);
        $query = str_replace('{ENDINTERVAL}',   $params->endInterval,   $query);

        return $query;
    }

}


<?php

namespace DruidFamiliar\QueryExecutor;

use DruidFamiliar\Exception;
use DruidFamiliar\Interfaces\IDruidQueryExecutor;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use Guzzle\Http\Message\Response;
use Guzzle\Http\Client;
use Guzzle\Http\Exception\CurlException;

class DruidNodeDruidQueryExecutor implements IDruidQueryExecutor
{
    /**
     * IP to Druid node
     * @var String
     */
    protected $ip;

    /**
     * Port to Druid node
     * @var Number
     */
    protected $port;

    /**
     * The endpoint to hit on the Druid node
     * @var string
     */
    protected $endpoint;

    /**
     * The protocol the Druid node is listening on. (http or https)
     *
     * @var int
     */
    protected $protocol;

    /**
     * HTTP Method to use
     *
     * @var string
     */
    protected $httpMethod = 'POST';

    /**
     * Headers to send
     *
     * @var array
     */
    protected $headers = array("content-type" => "application/json;charset=utf-8");

    public function __construct($ip, $port, $endpoint = '/druid/v2/', $protocol = 'http', $httpMethod = 'POST') {
        $this->ip = $ip;
        $this->port = $port;
        $this->endpoint = $endpoint;
        $this->setProtocol($protocol);
        $this->setHttpMethod($httpMethod);
    }

    public function getBaseUrl()
    {
        $baseUrl = $this->protocol . '://' . $this->ip . ':' . $this->port;
        $url = $baseUrl . $this->endpoint;
        return $url;
    }

    /**
     * Create a Guzzle Request object using the given JSON parameters
     *
     * @param string $query JSON String
     * @return \Guzzle\Http\Message\RequestInterface
     * @throws \Exception
     */
    public function createRequest($query)
    {
        $client = new \Guzzle\Http\Client();

        $method = $this->httpMethod;
        $uri = $this->getBaseUrl();
        $headers = $this->getHeaders();
        $options = array();

        if ( $method === 'POST' )
        {
            $postBody = $query;
            $request = $client->createRequest( $method, $uri, $headers, $postBody, $options );
        }
        else if ( $method === 'GET' )
        {
            $request = $client->createRequest( $method, $uri, $headers, null, $options );
            if ( $query ) {
                $queryObject = json_decode($query, true);
                $query = $request->getQuery();
                foreach ($queryObject as $key => $val) {
                    $query->set($key, $val);
                }
            }
        }
        else
        {
            throw new Exception('Unexpected HTTP Method: ' . $method);
        }

        return $request;
    }

    /**
     * Execute a Druid query using the provided query generator, parameters, and response payload handler.
     *
     * See DruidFamiliar\ResponseHandler\DoNothingResponseHandler.
     *
     * @param IDruidQueryGenerator $queryGenerator
     * @param IDruidQueryParameters $params
     * @param IDruidQueryResponseHandler $responseHandler
     * @return mixed
     */
    public function executeQuery(IDruidQueryGenerator $queryGenerator, IDruidQueryParameters $params, IDruidQueryResponseHandler $responseHandler)
    {
        $params->validate();

        $generatedQuery = $queryGenerator->generateQuery($params);

        // Create a request
        $request = $this->createRequest( $generatedQuery );

        // Send the request and parse the JSON response into an array
        try
        {
            $response = $request->send();
        }
        catch (\Guzzle\Http\Exception\CurlException $curlException)
        {
            throw new $curlException;
        }

        $formattedResponse = $responseHandler->handleResponse($response);

        return $formattedResponse;
    }

    /**
     * Get the HTTP Method.
     *
     * @return string
     */
    public function getHttpMethod()
    {
        return $this->httpMethod;
    }

    /**
     * Set the HTTP Method.
     *
     * Supported methods are: GET, POST
     *
     * @param $method
     * @throws \Exception
     */
    public function setHttpMethod($method)
    {
        $allowed_methods = array('GET', 'POST');

        $method = strtoupper( $method );

        if ( !in_array( $method, $allowed_methods ) ) {
            throw new Exception('Unsupported HTTP Method: ' . $method . '. Supported methods are: ' . join($allowed_methods, ', '));
        }

        $this->httpMethod = $method;
    }

    /**
     * Get the protocol.
     *
     * @return string
     */
    public function getProtocol()
    {
        return $this->protocol;
    }

    /**
     * Set the protocol.
     *
     * Supported protocols are: http, https
     *
     * @param string $protocol
     */
    public function setProtocol($protocol)
    {
        $allowedProtocols = array('http', 'https');

        $protocol = strtolower( $protocol );

        if ( !in_array( $protocol,$allowedProtocols ) ) {
            throw new Exception('Unsupported Protocol: ' . $protocol . '. Supported protocols are: ' . join($allowedProtocols, ', '));
        }

        $this->protocol = $protocol;
    }

    /**
     * @return String
     */
    public function getIp()
    {
        return $this->ip;
    }

    /**
     * @param String $ip
     */
    public function setIp($ip)
    {
        $this->ip = $ip;
    }

    /**
     * @return Number
     */
    public function getPort()
    {
        return $this->port;
    }

    /**
     * @param Number $port
     */
    public function setPort($port)
    {
        $this->port = $port;
    }

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

    /**
     * @param string $endpoint
     */
    public function setEndpoint($endpoint)
    {
        $this->endpoint = $endpoint;
    }

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

    /**
     * @param array $headers
     */
    public function setHeaders(array $headers)
    {
        $this->headers = $headers;
    }
}


<?php

namespace DruidFamiliar\ExampleGroupByQueries;

use DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject;
use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use Guzzle\Http\Message\Response;

/**
 * Class ReferralsByCompanyGroupByResponseHandler attempts to convert a Druid response into a ExampleReferralByCompanyResponseObject.
 *
 * @package DruidFamiliar\ResponseHandler
 */
class ReferralsByCompanyGroupByResponseHandler implements IDruidQueryResponseHandler
{

    /**
     * Hook function to handle response from server. Called with a PHP array of the JSON response from Druid.
     *
     * This hook must return the response, whether changed or not, so that the rest of the system can continue with it.
     *
     * @param Response $response
     * @return ExampleReferralByCompanyResponseObject
     */
    public function handleResponse($response)
    {
        $response = $response->json();

        if ( empty( $response ) ) {
            throw new \Exception('Unknown data source.');
        }

        $responseArray = array();

        foreach ( $response as $index => $chunk)
        {
            $timestamp = $chunk['timestamp'];
            $companyId = $chunk['event']['company_id'];
            $facilityId = $chunk['event']['facility_id'];
            $referrals = $chunk['event']['referral_count'];

            $responseObj = new \DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject(
                $companyId, $facilityId, $referrals, $timestamp
            );

            $responseArray[] = $responseObj;
        }

        return $responseArray;
    }

}


<?php

namespace DruidFamiliar\QueryGenerator;

use Exception;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\QueryParameters\GroupByQueryParameters;

/**
 * Class GroupByQueryGenerator
 * @package   DruidFamiliar\QueryGenerator
 * @author    Ernesto Spiro Peimbert Andreakis
 * @version   1.0
 * @category  WebPT
 * @copyright Copyright (c) 2014 WebPT, Inc.
 */
class GroupByQueryGenerator implements IDruidQueryGenerator
{
    /**
     * Generate a Druid query's JSON POST body
     *
     * @param IDruidQueryParameters $params
     *
     * @return string|void
     * @throws Exception
     */
    public function generateQuery(IDruidQueryParameters $params)
    {
        if(!$params instanceof GroupByQueryParameters)
        {
            throw new Exception('Expected $params to be instanceof GroupByQueryParameters');
        }

        $params->validate();
        $query = $params->getJSONString();
        return $query;
    }
}


<?php

namespace DruidFamiliar\QueryGenerator;

use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Exception\MissingParametersException;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use DruidFamiliar\QueryParameters\SimpleGroupByQueryParameters;

class SimpleGroupByDruidQueryGenerator implements IDruidQueryGenerator
{

    /**
     * As opposed to building the query body in PHP associative arrays, one could also template them.
     *
     * @var string
     */
    private $queryTemplate = <<<QUERYTEMPLATE
{
    "queryType": "{QUERYTYPE}",
    "dataSource": "{DATASOURCE}",
    "granularity": "{GRANULARITYSPEC.GRAN}",
    "dimensions": [ "{NON_TIME_DIMENSIONS}" ],
    "filter": [{FILTERS}],
    "aggregations": [{AGGREGATORS}],
    "postAggregations": [{POSTAGGREGATORS}],
    "intervals": ["{INTERVALS}"]
}
QUERYTEMPLATE;

    /**
     * Take parameters and return a valid Druid Query.
     * @param IDruidQueryParameters $params
     *
     * @param array $params
     * @return string Druid JSON POST Body
     * @throws \DruidFamiliar\Exception\MissingParametersException
     * @throws \Exception
     */
    public function generateQuery(IDruidQueryParameters $params)
    {
        /**
         * @var SimpleGroupByQueryParameters $params
         */
        if ( !$params instanceof SimpleGroupByQueryParameters ) {
            throw new Exception('Expected $params to be instanceof SimpleGroupByQueryParameters');
        }

        $params->validate();

        $query = $this->queryTemplate;

        // Assemble the query instead
        $queryKeys = array();

        // We always have these keys
        $queryKeys[] =  '"queryType": "{QUERYTYPE}"';
        $queryKeys[] =  '"dataSource": "{DATASOURCE}"';

        if ( is_array( $params->granularity ) && count( $params->granularity ) > 0 ) {
            $queryKeys[] =  '"granularity": {GRANULARITYSPEC.GRAN}';
        } else {
            $queryKeys[] = '"granularity": "{GRANULARITYSPEC.GRAN}"';
        }

        $queryKeys[] =  '"dimensions": [ "{NON_TIME_DIMENSIONS}" ]';

        if ( count( $params->filters ) > 0 ) {
            $queryKeys[] =  '"filter": {FILTERS}';
        }

        if ( count( $params->aggregators ) > 0 ) {
            $queryKeys[] =  '"aggregations": [{AGGREGATORS}]';
        }

        if ( count( $params->postAggregators ) > 0 ) {
            $queryKeys[] =  '"postAggregations": [{POSTAGGREGATORS}]';
        }

        $queryKeys[] =  '"intervals": ["{INTERVALS}"]';

        $query = "{" . join(",\n", $queryKeys) . "}";

        $query = str_replace('{QUERYTYPE}',             $params->queryType,                   $query);

        $query = str_replace('{DATASOURCE}',            $params->dataSource,                  $query);
        $query = str_replace('{INTERVALS}',             $params->intervals,                   $query);

        if ( is_array( $params->granularity ) && count( $params->granularity ) > 0 ) {
            $query = str_replace('{GRANULARITYSPEC.GRAN}', json_encode( $params->granularity ), $query);
        } else {
            $query = str_replace('{GRANULARITYSPEC.GRAN}',  $params->granularity,               $query);
        }

        $query = str_replace('{NON_TIME_DIMENSIONS}',   join('","', $params->dimensions),     $query);
        $query = str_replace('{FILTERS}',               join(",", $params->filters),          $query);
        $query = str_replace('{AGGREGATORS}',           join(",", $params->aggregators),      $query);
        $query = str_replace('{POSTAGGREGATORS}',       join(",", $params->postAggregators),  $query);

        return $query;
    }

}


<?php

namespace DruidFamiliar\QueryParameters;

use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Exception\MissingParametersException;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\DruidTime;
use DruidFamiliar\Interval;

/**
 * Class SimpleGroupByQueryParameters represents parameter values for a typical group by Druid query.
 *
 * @package DruidFamiliar
 */
class SimpleGroupByQueryParameters extends AbstractTaskParameters implements IDruidQueryParameters
{

    /**
     * Query Type
     *
     * @var string
     */
    public $queryType = "groupBy";

    /**
     * @var Interval
     */
    public $intervals;

    /**
     * @var string
     */
    public $granularityType = 'uniform';

    /**
     * @var string
     */
    public $granularity = 'DAY';

    /**
     * DataSource Name
     *
     * @var string
     */
    public $dataSource;

    /**
     * The data's time dimension key.
     *
     * @var string
     */
    public $timeDimension;

    /**
     * Array of strings representing the data's non-time dimensions' keys.
     *
     * @var array
     */
    public $dimensions;

    /**
     * Array of json encoded strings
     *
     * Intended to be set through $this->setFilters(...).
     *
     * @var array
     */
    public $filters = array();

    /**
     * Array of json encoded strings
     *
     * Intended to be set through $this->setAggregators(...).
     *
     * @var array
     */
    public $aggregators = array();

    /**
     * Array of json encoded strings
     *
     * Intended to be set through $this->setPostAggregators(...).
     *
     * @var array
     */
    public $postAggregators = array();

    public function setFilePath($path) {
        $fileInfo = pathinfo($path);
        $this->baseDir = $fileInfo['dirname'];
        $this->filePath = $fileInfo['basename'];
    }

    /**
     * Configure the aggregators for this request.
     *
     * @param $aggregatorsArray array PHP Array of aggregators
     */
    public function setAggregators($aggregatorsArray)
    {
        $this->aggregators = array();

        foreach( $aggregatorsArray as $aggregator)
        {
            $this->aggregators[] = json_encode( $aggregator );
        }

    }

    /**
     * Configure the filters for this request.
     *
     * @param $filtersArray PHP Array of aggregators
     */
    public function setFilters($filtersArray)
    {
        $this->filters = array();

        foreach( $filtersArray as $filter)
        {
            $this->filters[] = json_encode( $filter );
        }

    }

    /**
     * Configure the post aggregators for this request.
     *
     * @param $postAggregatorsArray array PHP Array of post aggregators
     */
    public function setPostAggregators($postAggregatorsArray)
    {
        $this->postAggregators = array();

        foreach( $postAggregatorsArray as $postAggregator)
        {
            $this->postAggregators[] = json_encode( $postAggregator );
        }

    }

    /**
     * @throws MissingParametersException
     */
    public function validate()
    {
        $this->validateForMissingParameters();

        $this->validateForEmptyParameters();
    }

    /**
     * @throws MissingParametersException
     */
    protected function validateForMissingParameters()
    {
        // Validate missing params
        $missingParams = array();

        $requiredParams = array(
            'queryType',
            'dataSource',
            'intervals',
            'granularity',
            'dimensions',
            'aggregators',
            'filters',
            'postAggregators'
        );

        foreach ($requiredParams as $requiredParam) {
            if ( !isset( $this->$requiredParam ) ) {
                $missingParams[] = $requiredParam;
            }
        }

        if ( count($missingParams) > 0 ) {
            throw new \DruidFamiliar\Exception\MissingParametersException($missingParams);
        }
    }

    /**
     * @throws MissingParametersException
     */
    protected function validateForEmptyParameters()
    {
        // Validate empty params
        $emptyParams = array();

        $requiredNonEmptyParams = array(
            'queryType',
            'dataSource'
        );

        foreach ($requiredNonEmptyParams as $requiredNonEmptyParam) {
            if ( !isset( $this->$requiredNonEmptyParam ) ) {
                $emptyParams[] = $requiredNonEmptyParam;
            }
        }

        if ( count($emptyParams) > 0 ) {
            throw new \DruidFamiliar\Exception\MissingParametersException($emptyParams);
        }
    }

    /**
     * @return Interval
     */
    public function getIntervals()
    {
        return $this->intervals;
    }

    /**
     * @param Interval $intervals
     */
    public function setIntervals(Interval $intervals)
    {
        $this->intervals = $intervals;
    }

    /**
     * @param string|\DateTime|DruidTime $intervalStart
     * @param string|\DateTime|DruidTime $intervalEnd
     */
    public function setIntervalByStartAndEnd($intervalStart, $intervalEnd)
    {
        $this->setIntervals(new Interval($intervalStart, $intervalEnd));
    }

    /**
     * Adjusts the datetime to make the interval "exclusive" of the datetime.
     * e.g., given
     * startDateTime=2014-06-18T12:30:01Z and
     * endDateTime=2014-06-18T01:00:00Z
     * return and Interval containing
     * startDateTime=2014-06-18T12:30:00Z and
     * endDateTime=2014-06-18T01:00:01Z
     *
     * @param $startDateTime
     * @param $endDateTime
     * @return void
     */
    public function setIntervalForQueryingUsingExclusiveTimes($startDateTime, $endDateTime)
    {
        $adjustedEndDateTime = new \DateTime($endDateTime);
        $adjustedEndDateTime->add(new \DateInterval('PT1S'));

        $this->setIntervals(new Interval($startDateTime, $adjustedEndDateTime));
    }
}


<?php
namespace pendalf89\tinymce;

use yii\helpers\Html;
use yii\helpers\Json;
use yii\widgets\InputWidget;

/**
 * TinyMCE renders a tinyMCE js plugin for WYSIWYG editing.
 */
class TinyMce extends InputWidget
{
    /**
     * @var array the options for the TinyMCE JS plugin.
     * Please refer to the TinyMCE JS plugin Web page for possible options.
     * @see http://www.tinymce.com/wiki.php/Configuration
     */
    public $clientOptions = [];

    /**
     * @var bool whether to set the on change event for the editor. This is required to be able to validate data.
     */
    public $triggerSaveOnBeforeValidateForm = true;

    /**
     * @inheritdoc
     */
    public function run()
    {
        if ($this->hasModel()) {
            $output = Html::activeTextarea($this->model, $this->attribute, $this->options);
        } else {
            $output = Html::textarea($this->name, $this->value, $this->options);
        }

        $this->registerClientScript();
        return $output;
    }

    /**
     * Registers Twitter TypeAhead Bootstrap plugin and the related events
     */
    protected function registerClientScript()
    {
        $js = [];
        $id = $this->options['id'];
        TinyMceAsset::register($this->view);
        $this->clientOptions['selector'] = "#{$id}";

        if (!empty($this->clientOptions['language'])) {
            $language_url = LanguageAsset::register($this->view)->baseUrl . "/{$this->clientOptions['language']}.js";
            $this->clientOptions['language_url'] = $language_url;
        }

        $options = Json::encode($this->clientOptions);
        $js[] = "tinymce.init($options);";

        if ($this->triggerSaveOnBeforeValidateForm) {
            $js[] = "$('#{$id}').parents('form').on('beforeValidate', function() { tinymce.triggerSave(); });";
        }
        $this->view->registerJs(implode("\n", $js));
    }
}


<?php

namespace DruidFamiliar\ExampleGroupByQueries;

class ReferralsByCompanyGroupByWithResponseObject extends ReferralsByCompanyGroupBy
{

    /**
     * Hook function to handle response from server.
     *
     * This hook must return the response, whether changed or not, so that the rest of the system can continue with it.
     *
     * @param array $response
     * @return array of ExampleReferralByCompanyResponseObject objects
     */
    public function handleResponse($response = Array())
    {
        $responseArray = array();

        foreach ( $response as $index => $chunk)
        {
            $timestamp = $chunk['timestamp'];
            $companyId = $chunk['event']['company_id'];
            $facilityId = $chunk['event']['facility_id'];
            $referrals = $chunk['event']['referral_count'];

            $dto = new \DruidFamiliar\ExampleResponseObjects\ExampleReferralByCompanyResponseObject(
                $companyId, $facilityId, $referrals, $timestamp
            );

            $responseArray[] = $dto;
        }

        return $responseArray;
    }

}


<?php

namespace DruidFamiliar\ResponseHandler;

use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use DruidFamiliar\Response\TimeBoundaryResponse;
use Guzzle\Http\Message\Response;
use Exception;

/**
 * Class TimeBoundaryResponseHandler attempts to convert a Druid response into a TimeBoundaryResponse.
 *
 * @package DruidFamiliar\ResponseHandler
 */
class TimeBoundaryResponseHandler implements IDruidQueryResponseHandler
{
    /**
     * Hook function to handle response from server. Called with a PHP array of the JSON response from Druid.
     *
     * This hook must return the response, whether changed or not, so that the rest of the system can continue with it.
     *
     * @param Response $response
     *
     * @return TimeBoundaryResponse|mixed
     * @throws Exception
     */
    public function handleResponse($response)
    {
        $response = $response->json();

        if(empty($response))
        {
            throw new Exception('Unknown data source.');
        }

        if(!isset ($response[0]['result']))
        {
            throw new Exception('Unexpected response format.');
        }
        if(!isset ($response[0]['result']['minTime']))
        {
            throw new Exception('Unexpected response format - response did not include minTime.');
        }
        if(!isset ($response[0]['result']['maxTime']))
        {
            throw new Exception('Unexpected response format - response did not include maxTime.');
        }

        $responseObj = new TimeBoundaryResponse();

        $responseObj->minTime = $response[0]['result']['minTime'];
        $responseObj->maxTime = $response[0]['result']['maxTime'];

        return $responseObj;
    }

}


<?php

namespace DruidFamiliar\QueryGenerator;

use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Exception\MissingParametersException;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use DruidFamiliar\QueryParameters\TimeBoundaryQueryParameters;
use Exception;

class TimeBoundaryDruidQueryGenerator implements IDruidQueryGenerator
{
    /**
     * Take parameters and return a valid Druid Query.
     * @param IDruidQueryParameters $params
     *
     * @param TimeBoundaryQueryParameters $params
     * @return string Query payload in JSON
     */
    public function generateQuery(IDruidQueryParameters $params)
    {
        /**
         * @var TimeBoundaryQueryParameters $params
         */
        if ( !$params instanceof TimeBoundaryQueryParameters ) {
            throw new Exception('Expected $params to be instanceof TimeBoundaryQueryParameters');
        }

        $params->validate();

        $responseObj = array(
            'queryType' => 'timeBoundary',
            "dataSource" => $params->dataSource
        );

        $responseString = json_encode( $responseObj );

        return $responseString;
    }
}


<?php

namespace DruidFamiliar\QueryGenerator;

use DateTime;
use DruidFamiliar;
use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Interfaces\IDruidQueryGenerator;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use DruidFamiliar\Interfaces\IDruidQueryResponseHandler;
use DruidFamiliar\QueryParameters\SegmentMetadataQueryParameters;
use Exception;

/**
 * Class SegmentMetadataDruidQueryGenerator generates Segment Metadata queries intended for use with Druid.
 *
 * TODO Handle optional bounds parameter
 *
 * @package DruidFamiliar\QueryGenerator
 */
class SegmentMetadataDruidQueryGenerator implements IDruidQueryGenerator
{
    /**
     * Take parameters and return a valid Druid Query.
     * @param IDruidQueryParameters $params
     *
     * @param SegmentMetadataQueryParameters $params
     * @return string Query payload in JSON
     * @throws \DruidFamiliar\Exception\MissingParametersException
     */
    public function generateQuery(IDruidQueryParameters $params)
    {
        /**
         * @var SegmentMetadataQueryParameters $params
         */
        if ( !$params instanceof SegmentMetadataQueryParameters )
        {
            throw new Exception('Expected $params to be instanceof SegmentMetadataQueryParameters');
        }

        $params->validate();

        $responseObj = array(
            'queryType' => 'segmentMetadata',
            "dataSource" => $params->dataSource,
            "intervals" => $params->intervals->__toString()
        );

        $responseString = json_encode( $responseObj );

        return $responseString;
    }
}


<?php

namespace DruidFamiliar\QueryParameters;

use DruidFamiliar\Abstracts\AbstractTaskParameters;
use DruidFamiliar\Exception\EmptyParametersException;
use DruidFamiliar\Exception\MissingParametersException;
use DruidFamiliar\Interfaces\IDruidQueryParameters;
use stdClass;

/**
 * Class GroupByQueryParameters
 * @package   DruidFamiliar\QueryParameters
 * @author    Ernesto Spiro Peimbert Andreakis
 * @version   1.0
 * @category  WebPT
 * @copyright Copyright (c) 2014 WebPT, Inc.
 */
class GroupByQueryParameters extends AbstractTaskParameters implements IDruidQueryParameters
{
    /**
     * This String should always be "groupBy"; this is the first thing Druid looks at to figure out how to interpret the query
     * @access protected
     * @var string
     */
    protected $queryType;
    /**
     * A String defining the data source to query, very similar to a table in a relational database, or a DataSource structure.
     * @access protected
     * @var string
     */
    protected $dataSource;
    /**
     * A JSON list of dimensions to do the groupBy over
     * @access protected
     * @var array
     */
    protected $dimensions;
    /**
     * Provides the functionality to sort and limit the set of results from a groupBy query
     * @see    http://druid.io/docs/0.6.154/LimitSpec.html
     * @access protected
     * @var stdClass
     */
    protected $limitSpec;
    /**
     * A JSON string identifying which rows from a groupBy query should be returned, by specifying conditions on aggregated values.
     * @access protected
     * @var stdClass
     */
    protected $having;
    /**
     * Defines the granularity of the query
     * @access protected
     * @var string
     */
    protected $granularity;
    /**
     * A filter is a JSON string indicating which rows of data should be included in the computation for a query.
     * @access protected
     * @var stdClass
     */
    protected $filter;
    /**
     * Specifications of processing over metrics available in Druid
     * @access protected
     * @var array
     */
    protected $aggregations;
    /**
     * Specifications of processing that should happen on aggregated values as they come out of Druid
     * @access protected
     * @var array
     */
    protected $postAggregations;
    /**
     * A JSON string representing ISO-8601 Intervals. This defines the time ranges to run the query over
     * @access protected
     * @var array
     */
    protected $intervals;
    /**
     * An additional JSON Object which can be used to specify certain flags.
     * @access protected
     * @var array
     */
    protected $context;
    /**
     * List of all parameters. Needed to create the JSON string
     * @access protected
     * @var array
     */
    protected $allParameters = array('queryType', 'dataSource', 'dimensions', 'limitSpecs', 'having', 'granularity', 'filter', 'aggregations', 'postAggregations', 'intervals', 'context');
    /**
     * Array of required params
     * @access protected
     * @var array
     */
    protected $requiredParams = array('queryType', 'dataSource', 'dimensions', 'granularity', 'aggregations', 'intervals');
    /**
     * Stores the missing parameters
     * @access protected
     * @var array
     */
    protected $missingParameters = array();
    /**
     * Stores any empty parameter
     * @access protected
     * @var array
     */
    protected $emptyParameters = array();

    /**
     * Class initializer
     */
    protected function initialize()
    {
        $this->queryType = 'groupBy';
    }

    /**
     * Class constructor
     */
    public function __construct()
    {
        $this->initialize();
    }

    /**
     * Validates the query has the necessary parameters
     *
     * @throws MissingParametersException
     */
    public function validate()
    {
        $flag = true;
        foreach($this->requiredParams as $param)
        {
            if(!isset($this->$param))
            {
                $this->missingParameters[] = $param;
                $flag                      = false;
            }
            else
            {
                $val = $this->$param;
                if(!is_array($val))
                {
                    $val = trim($val);
                }
                if(empty($val))
                {
                    $this->emptyParameters[] = $param;
                    $flag                    = false;
                }
            }
        }
        if(count($this->missingParameters) > 0)
        {
            throw new MissingParametersException($this->missingParameters);
        }
        if(count($this->emptyParameters) > 0)
        {
            throw new EmptyParametersException($this->emptyParameters);
        }
        return $flag;
    }

    /**
     * Converts the current object into a JSON representation to be used as a query
     * @return mixed|string
     */
    public function getJSONString()
    {
        $retString       = '{[DATA]}';
        $buffStringArray = array();
        foreach($this->allParameters as $param)
        {
            if(isset($this->$param))
            {
                $buffStringArray[] = "\"{$param}\":" . json_encode($this->$param);
            }
        }
        $buffString = implode(',', $buffStringArray);
        $retString  = str_replace('[DATA]', $buffString, $retString);
        return $retString;
    }

    /**
     * Returns the aggregations
     *
     * @return array
     */
    public function getAggregations()
    {
        return $this->aggregations;
    }

    /**
     * Sets the aggregations
     *
     * @param array $aggregations
     *
     * @return $this
     */
    public function setAggregations(array $aggregations)
    {
        foreach($aggregations as $aggregator)
        {
            $this->addAggregator($aggregator);
        }
        return $this;
    }

    /**
     * Adds a new aggregator to the aggregators array
     *
     * @param stdClass $aggregator
     *
     * @return $this
     */
    public function addAggregator($aggregator)
    {
        if(is_object($aggregator))
        {
            $this->aggregations[] = $aggregator;
        }
        return $this;
    }

    /**
     * Returns the context
     *
     * @return array
     */
    public function getContext()
    {
        return $this->context;
    }

    /**
     * Sets the context
     *
     * @param array $contexts
     *
     * @return $this
     */
    public function setContext(array $contexts)
    {
        foreach($contexts as $context)
        {
            $this->addContext($context);
        }
        return $this;
    }

    /**
     * Adds a new context to the contexts array
     *
     * @param string $context
     *
     * @return $this
     */
    public function addContext($context)
    {
        $this->context[] = $context;
        return $this;
    }

    /**
     * Returns the dataSource
     *
     * @return string
     */
    public function getDataSource()
    {
        return $this->dataSource;
    }

    /**
     * Sets the dataSource
     *
     * @param string $dataSource
     *
     * @return $this
     */
    public function setDataSource($dataSource)
    {
        $this->dataSource = $dataSource;
        return $this;
    }

    /**
     * Returns the dimensions
     *
     * @return array
     */
    public function getDimensions()
    {
        return $this->dimensions;
    }

    /**
     * Sets the dimensions
     *
     * @param array $dimensions
     *
     * @return $this
     */
    public function setDimensions(array $dimensions)
    {
        $this->dimensions = $dimensions;
        return $this;
    }

    /**
     * Adds a new dimension to the dimensions array
     *
     * @param string $dimension
     *
     * @return $this
     */
    public function addDimension($dimension)
    {
        $this->dimensions[] = $dimension;
        return $this;
    }

    /**
     * Returns the filter
     *
     * @return stdClass
     */
    public function getFilter()
    {
        return $this->filter;
    }

    /**
     * Sets the filter
     *
     * @param stdClass $filter
     *
     * @return $this
     */
    public function setFilter($filter)
    {
        if(is_object($filter))
        {
            $this->filter = $filter;
        }
        return $this;
    }

    /**
     * Returns the granularity
     *
     * @return string
     */
    public function getGranularity()
    {
        return $this->granularity;
    }

    /**
     * Sets the granularity
     *
     * @param string $granularity
     *
     * @return $this
     */
    public function setGranularity($granularity)
    {
        $this->granularity = $granularity;
        return $this;
    }

    /**
     * Returns the having
     *
     * @return stdClass
     */
    public function getHaving()
    {
        return $this->having;
    }

    /**
     * Sets the having
     *
     * @param stdClass $having
     *
     * @return $this
     */
    public function setHaving($having)
    {
        if(is_object($having))
        {
            $this->having = $having;
        }
        return $this;
    }

    /**
     * Returns the intervals
     *
     * @return array
     */
    public function getIntervals()
    {
        return $this->intervals;
    }

    /**
     * Sets the intervals
     *
     * @param array $intervals
     *
     * @return $this
     */
    public function setIntervals(array $intervals)
    {
        foreach($intervals as $interval)
        {
            $this->addInterval($interval);
        }
        return $this;
    }

    /**
     * Adds a new interval to the intervals array
     *
     * @param string $interval
     *
     * @return $this
     */
    public function addInterval($interval)
    {
        $this->intervals[] = $interval;
        return $this;
    }

    /**
     * Returns the limitSpec
     *
     * @return stdClass
     */
    public function getLimitSpec()
    {
        return $this->limitSpec;
    }

    /**
     * Sets the limitSpec
     *
     * @param stdClass $limitSpec
     *
     * @return $this
     */
    public function setLimitSpec($limitSpec)
    {
        $this->limitSpec = $limitSpec;
        return $this;
    }

    /**
     * Returns the postAggregations
     *
     * @return array
     */
    public function getPostAggregations()
    {
        return $this->postAggregations;
    }

    /**
     * Sets the postAggregations
     *
     * @param array $postAggregations
     *
     * @return $this
     */
    public function setPostAggregations(array $postAggregations)
    {
        foreach($postAggregations as $aggregator)
        {
            $this->addPostAggregator($aggregator);
        }
        return $this;
    }

    /**
     * Adds a new postaggregator to the postaggregators array
     *
     * @param stdClass $aggregator
     *
     * @return $this
     */
    public function addPostAggregator($aggregator)
    {
        if(is_object($aggregator))
        {
            $this->postAggregations[] = $aggregator;
        }
        return $this;
    }
}


<?php
namespace SwaggerUI\Controller;

use Zend\Mvc\Controller\AbstractActionController,
    Zend\View\Model\ViewModel;

use SwaggerUI\ConfigAwareInterface;

class SwaggerController extends AbstractActionController implements ConfigAwareInterface {
    protected $config;

    public function setConfig($config) {
        $this->config = $config;
    }

    /**
     * Display the SwaggerUI interface
     *
     * @return ViewModel
     */
    public function indexAction()
    {
        $helperManager = $this->getServiceLocator()->get('viewhelpermanager');
        $basePathHelper = $helperManager->get('basePath');

        // Default to /api/docs in case the configurable path is not set
        $swaggerUrl = '/api/docs';

        // Get swagger JSON url/path from config if set
        if (isset($this->config['swagger-json-url'])) {
            $swaggerUrl = $this->config['swagger-json-url'];
        }

        // Run through basePath helper if the string doesn't start with http
        if (substr($swaggerUrl, 0, 4) !== 'http') {
            $swaggerUrl = $basePathHelper->__invoke($swaggerUrl);
        }

        $viewModel = new ViewModel();
        $viewModel->setTerminal(true);
        $viewModel->setVariable('swaggerUrl', $swaggerUrl);

        return $viewModel->setTemplate('swagger-ui.phtml');
    }
}


<?php

namespace Neutrino\Database\Cli\Tasks;

/**
 * Class MigrateTask
 *
 * @package Neutrino\Database\Cli\Tasks
 */
class MigrateTask extends BaseTask
{
    /**
     * @description Run the database migrations.
     *
     * option      --database= : The database connection to use.
     * @option      --force : Force the operation to run when in production.
     * @option      --path= : The path of migrations files to be executed.
     * @option      --step : Force the migrations to be run so they can be rolled back individually.
     * @option      --pretend : Dump the SQL queries that would be run.
     */
    public function mainAction()
    {
        if (!$this->confirmToProceed()) {
            return;
        }

        $this->prepareDatabase();

        // Next, we will check to see if a path option has been defined. If it has
        // we will use the path relative to the root of this installation folder
        // so that migrations may be run for any path within the applications.
        $this->migrator->run($this->getMigrationPaths(), [
            'step'    => (int)$this->getOption('step'),
            'pretend' => $this->getOption('pretend') ?: false
        ]);

        // Once the migrator has run we will grab the note output and send it out to
        // the console screen, since the migrator itself functions without having
        // any instances of the OutputInterface contract passed into the class.
        foreach ($this->migrator->getNotes() as $note) {
            $this->line($note);
        }
    }

    /**
     * Prepare the migration database for running.
     *
     * @return void
     */
    protected function prepareDatabase()
    {
        if (!$this->migrator->storageExist()) {
            $this->callTask(InstallTask::class, 'main', $this->arguments, $this->options);
        }
    }
}


<?php

namespace Neutrino\Database\Schema;

use Closure;
use Neutrino\Support\Func;
use Phalcon\Di\Injectable;

class Builder extends Injectable
{
    /**
     * The database configuration.
     *
     * @var array
     */
    protected $dbConfig;

    /**
     * The schema grammar instance.
     *
     * @var \Neutrino\Database\Schema\DialectInterface
     */
    protected $grammar;

    /**
     * The Blueprint resolver callback.
     *
     * @var \Closure
     */
    protected $resolver;

    /**
     * The default string length for migrations.
     *
     * @var int
     */
    public static $defaultStringLength = 255;

    /**
     * Create a new database Schema manager.
     */
    public function __construct()
    {
        $this->dbConfig = $this->db->getDescriptor();

        $this->grammar = Dialect\Factory::create($this->db->getDialect());
    }

    /**
     * Set the default string length for migrations.
     *
     * @param  int $length
     *
     * @return void
     */
    public static function defaultStringLength($length)
    {
        static::$defaultStringLength = $length;
    }

    /**
     * Determine if the given table exists.
     *
     * @param string $table
     *
     * @return bool
     */
    public function hasTable($table)
    {
        return $this->db->tableExists($table, $this->dbConfig['dbname']);
    }

    /**
     * Determine if the given table has a given column.
     *
     * @param string $table
     * @param string $column
     *
     * @return bool
     */
    public function hasColumn($table, $column)
    {
        $tableColumns = array_map('strtolower', $this->listColumnsName($table));

        return in_array(strtolower($column), $tableColumns);
    }

    /**
     * Determine if the given table has given columns.
     *
     * @param  string $table
     * @param  array  $columns
     *
     * @return bool
     */
    public function hasColumns($table, array $columns)
    {
        $tableColumns = array_map('strtolower', $this->listColumnsName($table));

        foreach ($columns as $column) {
            if (!in_array(strtolower($column), $tableColumns)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Get the data type for the given column name.
     *
     * @param string $table
     * @param string $column
     *
     * @return string
     */
    public function getColumnType($table, $column)
    {
        $col = $this->describeColumn($table, $column);

        if (!is_null($col)) {
            return $col->getType();
        }

        return null;
    }

    /**
     * Get the column listing for a given table.
     *
     * @param  string $table
     *
     * @return \Phalcon\Db\Column[]|\Phalcon\Db\ColumnInterface[]
     */
    public function getColumnListing($table)
    {
        return $this->db->describeColumns($table, $this->dbConfig['dbname']);
    }

    /**
     * Modify a table on the schema.
     *
     * @param  string   $table
     * @param  \Closure $callback
     *
     * @return void
     */
    public function table($table, Closure $callback)
    {
        $this->build(Func::tap($this->createBlueprint($table), function (Blueprint $blueprint) use ($callback) {
            $blueprint->update();

            $callback($blueprint);
        }));
    }

    /**
     * Create a new table on the schema.
     *
     * @param  string   $table
     * @param  \Closure $callback
     *
     * @return void
     */
    public function create($table, Closure $callback)
    {
        $this->build(Func::tap($this->createBlueprint($table), function (Blueprint $blueprint) use ($callback) {
            $blueprint->create();

            $callback($blueprint);
        }));
    }

    /**
     * Drop a table from the schema.
     *
     * @param  string $table
     *
     * @return void
     */
    public function drop($table)
    {
        $this->build(Func::tap($this->createBlueprint($table), function (Blueprint $blueprint) {
            $blueprint->drop();
        }));
    }

    /**
     * Drop a table from the schema if it exists.
     *
     * @param  string $table
     *
     * @return void
     */
    public function dropIfExists($table)
    {
        $this->build(Func::tap($this->createBlueprint($table), function (Blueprint $blueprint) {
            $blueprint->dropIfExists();
        }));
    }

    /**
     * Drop all tables from the database.
     *
     * @return void
     *
     * @throws \LogicException
     */
    public function dropAllTables()
    {
        @$this->disableForeignKeyConstraints();

        foreach ($this->db->listTables() as $table) {
            $this->drop($table);
        };

        @$this->enableForeignKeyConstraints();
    }

    /**
     * Rename a table on the schema.
     *
     * @param  string $from
     * @param  string $to
     *
     * @return void
     */
    public function rename($from, $to)
    {
        $this->build(Func::tap($this->createBlueprint($from), function (Blueprint $blueprint) use ($to) {
            $blueprint->update();

            $blueprint->rename($to);
        }));
    }

    /**
     * Execute a raw SQL Command
     *
     * @param string $sql
     *
     * @return void
     */
    public function execute($sql)
    {
        $this->build(Func::tap($this->createBlueprint(null), function (Blueprint $blueprint) use ($sql) {
            $blueprint->raw();

            $blueprint->sql($sql);
        }));
    }

    /**
     * Enable foreign key constraints.
     *
     * @return bool
     */
    public function enableForeignKeyConstraints()
    {
        return $this->db->execute(
            $this->grammar->enableForeignKeyConstraints()
        );
    }

    /**
     * Disable foreign key constraints.
     *
     * @return bool
     */
    public function disableForeignKeyConstraints()
    {
        return $this->db->execute(
            $this->grammar->disableForeignKeyConstraints()
        );
    }

    /**
     * Execute the blueprint to build / modify the table.
     *
     * @param  \Neutrino\Database\Schema\Blueprint $blueprint
     *
     * @return void
     */
    protected function build(Blueprint $blueprint)
    {
        $blueprint->build($this->db, $this->grammar);
    }

    /**
     * Create a new command set with a Closure.
     *
     * @param  string        $table
     * @param  \Closure|null $callback
     *
     * @return \Neutrino\Database\Schema\Blueprint
     */
    protected function createBlueprint($table, Closure $callback = null)
    {
        if (isset($this->resolver)) {
            return call_user_func($this->resolver, $table, $callback);
        }

        return new Blueprint($table, $callback);
    }

    /**
     * @param string $table
     * @param string $column
     *
     * @return null|\Phalcon\Db\ColumnInterface
     */
    protected function describeColumn($table, $column)
    {
        foreach ($this->db->describeColumns($table, $this->dbConfig['dbname']) as $col) {
            if ($col->getName() == $column) {
                return $col;
            }
        }

        return null;
    }

    /**
     * @param string                             $table
     * @param \Phalcon\Db\ColumnInterface[]|null $tableColumns
     *
     * @return array
     */
    protected function listColumnsName($table, array $tableColumns = null)
    {
        if (is_null($tableColumns)) {
            $tableColumns = $this->getColumnListing($table);
        }

        $columnsName = [];

        foreach ($tableColumns as $tableColumn) {
            $columnsName[] = $tableColumn->getName();
        }

        return $columnsName;
    }

    /**
     * Set the Schema Blueprint resolver callback.
     *
     * @param  \Closure $resolver
     *
     * @return void
     */
    public function blueprintResolver(Closure $resolver)
    {
        $this->resolver = $resolver;
    }
}


<?php

namespace Igniter\Flame\Database\Attach;

use Exception;
use File;
use FilesystemIterator;
use Igniter\Flame\Database\Model;
use Log;
use Storage;
use Symfony\Component\HttpFoundation\File\File as SymfonyFile;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use URL;

class Media extends Model
{
    use \Igniter\Flame\Database\Traits\Sortable;

    const SORT_ORDER = 'priority';

    protected $table = 'media_attachments';

    public $timestamps = TRUE;

    protected $guarded = ['disk'];

    /**
     * @var array Known image extensions.
     */
    public static $imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];

    /**
     * @var array Hidden fields from array/json access
     */
    protected $hidden = ['attachment_type', 'attachment_id', 'is_public'];

    /**
     * The attributes that should be casted to native types.
     *
     * @var array
     */
    public $casts = [
        'manipulations' => 'array',
        'custom_properties' => 'array',
    ];

    /**
     * @var array Mime types
     */
    protected $autoMimeTypes = [
        'gif' => 'image/gif',
        'png' => 'image/png',
        'jpg' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'webp' => 'image/webp',
        'pdf' => 'application/pdf',
        'docx' => 'application/msword',
        'xlsx' => 'application/excel',
    ];

    public $fileToAdd;

    /**
     * Set the polymorphic relation.
     *
     * @return mixed
     */
    public function attachment()
    {
        return $this->morphTo('attachment');
    }

    /**
     * Creates a file object from a file an uploaded file.
     * @param \Symfony\Component\HttpFoundation\File\UploadedFile $uploadedFile
     * @param null $tag
     * @return self
     */
    public function addFromRequest(UploadedFile $uploadedFile, $tag = null)
    {
        $this->getMediaAdder()
             ->performedOn($this->attachment)
             ->useMediaTag($tag)
             ->fromFile($uploadedFile);

        return $this;
    }

    /**
     * Creates a file object from a file on the disk.
     * @param $filePath
     * @param null $tag
     * @return self|void
     */
    public function addFromFile($filePath, $tag = null)
    {
        if (is_null($filePath))
            return;

        $this->getMediaAdder()
             ->performedOn($this->attachment)
             ->useMediaTag($tag)
             ->fromFile(new SymfonyFile($filePath));

        return $this;
    }

    /**
     * Creates a file object from raw data.
     *
     * @param $rawData string Raw data
     * @param $filename string Filename
     *
     * @param null $tag
     * @return $this|void
     */
    public function addFromRaw($rawData, $filename, $tag = null)
    {
        if (is_null($rawData))
            return;

        $tempPath = temp_path($filename);
        File::put($tempPath, $rawData);

        $this->addFromFile($tempPath, $tag);
        File::delete($tempPath);

        return $this;
    }

    /**
     * Creates a file object from url
     * @param $url string URL
     * @param $filename string Filename
     * @param null $tag
     * @return $this
     * @throws \Exception
     */
    public function addFromUrl($url, $filename = null, $tag = null)
    {
        if (!$stream = @fopen($url, 'rb'))
            throw new Exception(sprintf('Error opening file "%s"', $url));

        return $this->addFromRaw(
            $stream,
            !empty($filename) ? $filename : File::basename($url),
            $tag
        );
    }

    //
    // Events
    //

    public function beforeSave()
    {
        if (!is_null($this->fileToAdd)) {
            if ($this->fileToAdd instanceof UploadedFile) {
                $this->addFromRequest($this->fileToAdd);
            }
            else {
                $this->addFromFile($this->fileToAdd);
            }

            $this->fileToAdd = null;
        }
    }

    /**
     * After model is deleted
     * - clean up it's thumbnails
     */
    public function afterDelete()
    {
        try {
            $this->deleteThumbs();
            $this->deleteFile();
        }
        catch (Exception $ex) {
            Log::error($ex);
        }
    }

    //
    // Attribute mutators
    //

    /**
     * Determine the type of a file.
     *
     * @return string
     */
    public function getTypeAttribute()
    {
        return $this->getMimeType();
    }

    public function getExtensionAttribute()
    {
        return $this->getExtension();
    }

    /**
     * Helper attribute for get image width.
     * @return string
     */
    public function getWidthAttribute()
    {
        if ($this->isImage()) {
            $dimensions = $this->getImageDimensions();

            return $dimensions[0];
        }
    }

    /**
     * Helper attribute for get image height.
     * @return string
     */
    public function getHeightAttribute()
    {
        if ($this->isImage()) {
            $dimensions = $this->getImageDimensions();

            return $dimensions[1];
        }
    }

    public function getHumanReadableSizeAttribute()
    {
        return $this->sizeToString($this->size);
    }

    //
    // Getters
    //

    /**
     * Returns the file name without path
     */
    public function getFilename()
    {
        return $this->file_name;
    }

    /**
     * Returns the file extension.
     */
    public function getExtension()
    {
        return File::extension($this->file_name);
    }

    /**
     * Returns the last modification date as a UNIX timestamp.
     * @return int
     */
    public function getLastModified($fileName = null)
    {
        if (!$fileName)
            $fileName = $this->disk_name;

        return $this->getStorageDisk()->lastModified($this->getStoragePath().$fileName);
    }

    /**
     * Returns the public address to access the file.
     */
    public function getPath()
    {
        return $this->getPublicPath().$this->getPartitionDirectory().$this->name;
    }

    /**
     * Returns a local path to this file. If the file is stored remotely,
     * it will be downloaded to a temporary directory.
     */
    public function getFullDiskPath()
    {
        return $this->getStorageDisk()->path($this->getDiskPath());
    }

    /**
     * Returns the path to the file, relative to the storage disk.
     * @return string
     */
    public function getDiskPath()
    {
        return $this->getStoragePath().$this->name;
    }

    /**
     * Determines if the file is flagged "public" or not.
     */
    public function isPublic()
    {
        if (is_null($this->is_public))
            return TRUE;

        return $this->is_public;
    }

    /**
     * Returns the file size as string.
     * @return string Returns the size as string.
     */
    public function sizeToString()
    {
        return File::sizeToString($this->file_size);
    }

    public function getMimeType()
    {
        if (!is_null($this->mime_type))
            return $this->mime_type;

        if ($type = $this->getTypeFromExtension())
            return $this->mime_type = $type;

        return null;
    }

    public function getTypeFromExtension()
    {
        $ext = $this->getExtension();
        if (isset($this->autoMimeTypes[$ext])) {
            return $this->autoMimeTypes[$ext];
        }
    }

    /**
     * Generates a unique name from the supplied file name.
     */
    public function getUniqueName()
    {
        if (!is_null($this->name))
            return $this->name;

        $ext = strtolower($this->getExtension());

        $name = str_replace('.', '', uniqid(null, TRUE));
        return $this->name = $name.(strlen($ext) ? '.'.$ext : '');
    }

    public function getDiskName()
    {
        if (!is_null($this->disk))
            return $this->disk;

        $diskName = config('system.assets.attachment.disk');
        if (is_null(config("filesystems.disks.{$diskName}")))
            throw new Exception("There is no filesystem disk named '{$diskName}''");

        return $this->disk = $diskName;
    }

    public function getDiskDriverName()
    {
        return strtolower(config("filesystems.disks.{$this->disk}.driver"));
    }

    //
    //
    //

    /**
     * Delete all thumbnails for this file.
     */
    public function deleteThumbs()
    {
        $pattern = 'thumb_'.$this->id.'_';

        $directory = $this->getStoragePath();
        $allFiles = $this->getStorageDisk()->files($directory);
        $paths = array_filter($allFiles, function ($file) use ($pattern) {
            return starts_with(basename($file), $pattern);
        });

        $this->getStorageDisk()->delete($paths);
    }

    /**
     * Delete file contents from storage device.
     * @param null $fileName
     * @return void
     */
    protected function deleteFile($fileName = null)
    {
        if (!$fileName) {
            $fileName = $this->name;
        }

        $directory = $this->getStoragePath();
        $filePath = $directory.$fileName;

        if ($this->getStorageDisk()->exists($filePath)) {
            $this->getStorageDisk()->delete($filePath);
        }

        $this->deleteEmptyDirectory($directory);
    }

    /**
     * Checks if directory is empty then deletes it,
     * three levels up to match the partition directory.
     * @param string $directory
     * @return void
     */
    protected function deleteEmptyDirectory($directory = null)
    {
        if (!$this->isDirectoryEmpty($directory))
            return;

        $this->getStorageDisk()->deleteDirectory($directory);

        $directory = dirname($directory);
        if (!$this->isDirectoryEmpty($directory))
            return;

        $this->getStorageDisk()->deleteDirectory($directory);

        $directory = dirname($directory);
        if (!$this->isDirectoryEmpty($directory))
            return;

        $this->getStorageDisk()->deleteDirectory($directory);
    }

    /**
     * Returns true if a directory contains no files.
     * @param $directory
     * @return bool|null
     */
    protected function isDirectoryEmpty($directory)
    {
        $path = $this->getStorageDisk()->path($directory);
        return !(new FilesystemIterator($path))->valid();
    }

    /**
     * Check file exists on storage device.
     * @param string $fileName
     * @return bool
     */
    protected function hasFile($fileName = null)
    {
        $filePath = $this->getStoragePath().$fileName;
        return $this->getStorageDisk()->exists($filePath);
    }

    //
    // Image handling
    //

    /**
     * Checks if the file extension is an image and returns true or false.
     */
    public function isImage()
    {
        return in_array(strtolower($this->getExtension()), static::$imageExtensions);
    }

    /**
     * Generates and returns a thumbnail url.
     * @param int $width
     * @param int $height
     * @param array $options
     * @return string
     */
    public function getThumb($options = [])
    {
        if (!$this->isImage())
            return $this->getPath();

        $options = $this->getDefaultThumbOptions($options);

        $thumbFile = $this->getThumbFilename($options);
        if (!$this->hasFile($thumbFile))
            $this->makeThumb($thumbFile, $options);

        return $this->getPublicPath().$this->getPartitionDirectory().$thumbFile;
    }

    public function outputThumb($options = [])
    {

    }

    public function getDefaultThumbPath($thumbPath, $default = null)
    {
        if (!$default) {
            $this->getStorageDisk()->put($thumbPath, Manipulator::decodedBlankImage());
            $default = $thumbPath;
        }

        return $this->getStorageDisk()->path($default);
    }

    /**
     * Get image dimensions
     * @return array|bool
     */
    protected function getImageDimensions()
    {
        return getimagesize($this->getFullDiskPath());
    }

    /**
     * Generates a thumbnail filename.
     * @param int $width
     * @param int $height
     * @param array $options
     * @return string
     */
    protected function getThumbFilename($options)
    {
        return 'thumb_'
            .$this->id.'_'
            .$options['width'].'_'.$options['height'].'_'.$options['fit'].'_'
            .substr(md5(serialize(array_except($options, ['width', 'height', 'fit']))), 0, 8).
            '.'.$options['extension'];
    }

    /**
     * Returns the default thumbnail options.
     * @param array $override
     * @return array
     */
    protected function getDefaultThumbOptions($override = [])
    {
        $defaultOptions = [
            'fit' => 'contain',
            'width' => 0,
            'height' => 0,
            'quality' => 90,
            'sharpen' => 0,
            'extension' => 'auto',
        ];

        if (!is_array($override))
            $override = ['fit' => $override];

        $options = array_merge($defaultOptions, $override);

        if (strtolower($options['extension']) == 'auto')
            $options['extension'] = strtolower($this->getExtension());

        return $options;
    }

    /**
     * Generate the thumbnail
     * @param $thumbFile
     * @param array $options
     */
    protected function makeThumb($thumbFile, $options)
    {
        $thumbFile = $this->getStoragePath().$thumbFile;
        $thumbPath = $this->getStorageDisk()->path($thumbFile);
        $filePath = $this->getStorageDisk()->path($this->getDiskPath());

        if (!$this->hasFile($this->name))
            $filePath = $this->getDefaultThumbPath($thumbFile, array_get($options, 'default'));

        Manipulator::make($filePath)
                   ->manipulate(array_except($options, ['extension', 'default']))
                   ->save($thumbPath);
    }

    //
    // Custom Properties
    //

    public function getCustomProperties()
    {
        return $this->custom_properties;
    }

    /*
     * Determine if the media item has a custom property with the given name.
     */
    public function hasCustomProperty($propertyName)
    {
        return array_has($this->custom_properties, $propertyName);
    }

    /**
     * Get if the value of custom property with the given name.
     *
     * @param string $propertyName
     * @param mixed $default
     *
     * @return mixed
     */
    public function getCustomProperty($propertyName, $default = null)
    {
        return array_get($this->custom_properties, $propertyName, $default);
    }

    /**
     * @param string $name
     * @param mixed $value
     *
     * @return $this
     */
    public function setCustomProperty($name, $value)
    {
        $customProperties = $this->custom_properties;

        array_set($customProperties, $name, $value);

        $this->custom_properties = $customProperties;

        return $this;
    }

    /**
     * @param string $name
     *
     * @return $this
     */
    public function forgetCustomProperty($name)
    {
        $customProperties = $this->custom_properties;

        array_forget($customProperties, $name);

        $this->custom_properties = $customProperties;

        return $this;
    }

    //
    // Configuration
    //

    /**
     * Define the internal storage path, override this method to define.
     */
    public function getStoragePath()
    {
        return $this->getStorageDirectory().$this->getPartitionDirectory();
    }

    /**
     * Define the public address for the storage path.
     */
    public function getPublicPath()
    {
        $mediaPath = config('system.assets.attachment.path', '/storage/app/attachments');
        $mediaPath = $this->isPublic()
            ? $mediaPath.'/public'
            : $mediaPath.'/protected';

        return URL::asset($mediaPath).'/';
    }

    /**
     * Define the internal working path, override this method to define.
     */
    public function getTempPath()
    {
        $path = temp_path().'/attachments';

        if (!File::isDirectory($path))
            File::makeDirectory($path, 0777, TRUE, TRUE);

        return $path;
    }

    /**
     * Define the internal storage folder, override this method to define.
     */
    public function getStorageDirectory()
    {
        $mediaFolder = config('system.assets.attachment.folder', 'attachments');
        return $this->isPublic() ? $mediaFolder.'/public/' : $mediaFolder.'/protected/';
    }

    /**
     * Generates a partition for the file.
     * @return mixed
     */
    public function getPartitionDirectory()
    {
        return implode('/', array_slice(str_split($this->name, 3), 0, 3)).'/';
    }

    /**
     * @return \Illuminate\Filesystem\FilesystemAdapter
     * @throws \Exception
     */
    protected function getStorageDisk()
    {
        return Storage::disk($this->getDiskName());
    }

    protected function getMediaAdder()
    {
        return app(MediaAdder::class)->on($this);
    }
}


<?php

namespace Neutrino\Database\Schema\Dialect;

use Neutrino\Database\Schema;
use Neutrino\Support\Fluent;
use Phalcon\Db\Column;

/**
 * Trait PostgresqlTrait
 *
 * @package Neutrino\Database\Schema\Dialect
 */
trait PostgresqlTrait
{

    use Schema\DialectTrait {
        typeTime as _typeTime;
        typeDateTime as _typeDateTime;
        typeTimestamp as _typeTimestamp;
    }

    /**
     * Get SQL Enable foreign key constraints.
     *
     * @return string
     */
    public function enableForeignKeyConstraints()
    {
        return 'SET CONSTRAINTS ALL IMMEDIATE;';
    }

    /**
     * Get SQL Disable foreign key constraints.
     *
     * @return string
     */
    public function disableForeignKeyConstraints()
    {
        return 'SET CONSTRAINTS ALL DEFERRED;';
    }

    /**
     * Create the column type definition for a mediumText type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeMediumText(Fluent $column)
    {
        return $this->typeText($column);
    }

    /**
     * Create the column type definition for a longText type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeLongText(Fluent $column)
    {
        return $this->typeText($column);
    }

    /**
     * Create the column type definition for a enum type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeEnum(Fluent $column)
    {
        $values = array_map(function ($a) {
            return "'{$a}'";
        }, $column->get('values'));

        $maxlen = 0;
        foreach ($values as $value) {
            $maxlen = max($maxlen, strlen($value));
        }

        return [
            'type'          => "varchar($maxlen) check (\"{$column->get('name')}\" in (" . implode(', ', $values) . '))',
            'typeReference' => -1
        ];
    }

    protected function compileTimableColumn(Fluent $column, $type, $withTz = false)
    {
        $precision = !empty($column['precision']) ? '(' . $column['precision'] . ')' : '';

        $type .= $precision;

        if ($withTz) {
            $type .= ' WITH TIME ZONE';
        }

        if (!empty($column['default'])) {
            $type .= ' DEFAULT ' . $column['default'] . $precision;

            if ($withTz) {
                $type .= ' WITH TIME ZONE';
            }

            unset($column['default']);
        }

        return $type;
    }

    /**
     * Create the column type definition for a timeTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeTime(Fluent $column)
    {
        if (!empty($column['precision'])) {
            return [
                'type'          => $this->compileTimableColumn($column, 'TIME'),
                'typeReference' => Column::TYPE_DATETIME,
            ];
        }

        return $this->_typeTime($column);
    }

    /**
     * Create the column type definition for a dateTimeTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeDateTime(Fluent $column)
    {
        if (!empty($column['precision'])) {
            return [
                'type'          => $this->compileTimableColumn($column, 'TIMESTAMP'),
                'typeReference' => Column::TYPE_DATETIME,
            ];
        }

        return $this->_typeDateTime($column);
    }

    /**
     * Create the column type definition for a timestampTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeTimestamp(Fluent $column)
    {
        if (!empty($column['precision'])) {
            return [
                'type'          => $this->compileTimableColumn($column, 'TIMESTAMP'),
                'typeReference' => Column::TYPE_TIMESTAMP,
            ];
        }

        return $this->_typeTimestamp($column);
    }

    /**
     * Create the column type definition for a timeTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeTimeTz(Fluent $column)
    {
        return [
            'type'          => $this->compileTimableColumn($column, 'TIME', true),
            'typeReference' => Column::TYPE_DATETIME,
        ];
    }

    /**
     * Create the column type definition for a dateTimeTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeDateTimeTz(Fluent $column)
    {
        return [
            'type'          => $this->compileTimableColumn($column, 'TIMESTAMP', true),
            'typeReference' => Column::TYPE_DATETIME,
        ];
    }

    /**
     * Create the column type definition for a timestampTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeTimestampTz(Fluent $column)
    {
        return [
            'type'          => $this->compileTimableColumn($column, 'TIMESTAMP', true),
            'typeReference' => Column::TYPE_TIMESTAMP,
        ];
    }

    /**
     * Create the column type definition for a uuid type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeUuid(Fluent $column)
    {
        return [
            'type'          => 'uuid',
            'typeReference' => Column::TYPE_CHAR
        ];
    }

    /**
     * Create the column type definition for a IP Address type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeIpAddress(Fluent $column)
    {
        return [
            'type'          => 'inet',
            'typeReference' => Column::TYPE_VARCHAR
        ];
    }

    /**
     * Create the column type definition for a MAC Address type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeMacAddress(Fluent $column)
    {
        return [
            'type'          => 'macaddr',
            'typeReference' => Column::TYPE_VARCHAR
        ];
    }

    /**
     * Generates SQL for rename table
     *
     * @param string      $from
     * @param string      $to
     * @param null|string $schema
     *
     * @return string
     */
    public function renameTable($from, $to, $schema = null)
    {
        return "ALTER TABLE " . $this->prepareTable($from, $schema) . " RENAME TO " . $this->prepareTable($to, $schema);
    }
}


<?php

namespace Neutrino\HttpClient\Provider\Curl;

use Neutrino\HttpClient\Contract\Streaming\Streamable;
use Neutrino\HttpClient\Contract\Streaming\Streamize;
use Neutrino\HttpClient\Provider\Curl;
use Phalcon\Events\ManagerInterface;

/**
 * Class Streaming
 *
 * @package Neutrino\HttpClient\Provider\Curl
 */
class Streaming extends Curl implements Streamable
{
    use Streamize;

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

    /**
     * Curl WRITEFUNCTION handler
     *
     * @param resource $ch
     * @param string   $content
     *
     * @return int
     */
    protected function curlWriteFunction($ch, $content)
    {
        if (!$this->hasStarted) {
            $this->hasStarted = true;

            $this->getEventsManager()->fire(self::EVENT_START, $this);
        }

        $length = strlen($content);

        $this->getEventsManager()->fire(self::EVENT_PROGRESS, $this, $content);

        return $length;
    }

    /**
     * Send request
     */
    public function send()
    {
        parent::send();

        $this->getEventsManager()->fire(self::EVENT_FINISH, $this);
    }

    /**
     * @inheritdoc
     */
    protected function curlOptions($ch)
    {
        parent::curlOptions($ch);

        curl_setopt_array($ch,
            [
                CURLOPT_RETURNTRANSFER => false,
                CURLOPT_WRITEFUNCTION  => [$this, 'curlWriteFunction'],
            ]);

        if (isset($this->bufferSize)) {
            curl_setopt($ch, CURLOPT_BUFFERSIZE, $this->bufferSize);
        }
    }
}


<?php

namespace Neutrino\Foundation\Cli\Tasks;

use Neutrino\Assets\ClosureCompiler;
use Neutrino\Cli\Output\Table;
use Neutrino\Cli\Task;

/**
 * Class AssetsTask
 *
 * Neutrino\Foundation\Cli\Tasks
 */
class AssetsJsTask extends Task
{
    /**
     * Compilation, Optimization, Minification of assets js.
     * Use the Closure Compile API.
     *
     * @option --verbose-externs : Display errors & warnings of externals files
     */
    public function mainAction()
    {
        $this->line('Compiling js... ');

        $options = $this->config->assets->js->toArray();

        $result = $this->getDI()->get(ClosureCompiler::class)->compile($options);

        if (!empty($result['errors'])) {
            $this->outputErrors($result['errors'], 'errors', 'error', $options);
        }

        if (!empty($result['warnings'])) {
            $this->outputErrors($result['warnings'], 'warnings', 'warn', $options);
        }

        $this->block([str_pad(strtoupper('STATISTICS'), 40, ' ', STR_PAD_BOTH)], 'question', 4);

        $statistics = [];
        foreach ($result['statistics'] as $type => $statistic) {
            $statistics[] = ['stats' => $type, 'value' => $statistic];
        }
        $this->table($statistics);

        $this->info('Success');
    }

    private function outputErrors($items, $type, $display, $options)
    {
        $this->block([str_pad(strtoupper($type), 40, ' ', STR_PAD_BOTH)], $display, 4);

        if (!$this->hasOption('verbose-externs')) {
            $externs = $this->extractExternsErrors($items, $options['compile']['externs_url']);

            foreach ($externs as $file => $count) {
                $externs[$file] = "$file : $count";
            }

            $this->block(array_merge(['External ' . $type . ' :'], $externs), 'line');
        }

        if(!empty($items)){
            $this->block(array_merge(['Internal ' . $type . ' : ' . count($items)]), $display);

            foreach ($items as $item) {
                $this->table($this->formatErrorsOrWarnings($item), [], Table::NO_HEADER);
            }
        }
    }

    private function formatErrorsOrWarnings($item)
    {
        $row = [];
        foreach ($item as $type => $value) {
            $row[] = [$type, str_replace("\n", ', ', $value)];
        }

        return $row;
    }

    private function extractExternsErrors(&$result, $externs)
    {
        $count = [];
        foreach ($result as $k => $item) {
            if (in_array($item['file'], $externs)) {
                unset($result[$k]);
                isset($count[$item['file']])
                  ? $count[$item['file']]++
                  : $count[$item['file']] = 1;
            }
        }

        $result = array_values($result);

        return $count;
    }
}


<?php namespace Igniter\Flame\Foundation\Bootstrap;

use Illuminate\Contracts\Foundation\Application;

class RegisterTastyIgniter
{
    /**
     * Register specifics for TastyIgniter.
     *
     * @param  \Illuminate\Contracts\Foundation\Application $app
     *
     * @return void
     */
    public function bootstrap(Application $app)
    {
        // Workaround for CLI and URL based in subdirectory
        if ($app->runningInConsole()) {
            $app['url']->forceRootUrl($app['config']->get('app.url'));
        }

        // Register singletons
        $app->singleton('string', function () {
            return new \Igniter\Flame\Support\StrHelper;
        });

        // Change extensions and themes paths based on config
        if ($extensionsPath = $app['config']->get('system.extensionsPath'))
            $app->useExtensionsPath($extensionsPath);

        if ($themesPath = $app['config']->get('system.themesPath'))
            $app->useThemesPath($themesPath);

        if ($assetsPath = $app['config']->get('system.assetsPath'))
            $app->useAssetsPath($assetsPath);

        // Set execution context
        $requestPath = $this->normalizeUrl($app['request']->path());
        $adminUri = $this->normalizeUrl($app['config']->get('system.adminUri', 'admin'));
        $app->setAppContext(starts_with($requestPath, $adminUri) ? 'admin' : 'main');
    }

    /**
     * Adds leading slash from a URL.
     *
     * @param string $url URL to normalize.
     *
     * @return string Returns normalized URL.
     */
    protected function normalizeUrl($url)
    {
        if (substr($url, 0, 1) != '/')
            $url = '/'.$url;

        if (!strlen($url))
            $url = '/';

        return $url;
    }
}


<?php

namespace Neutrino\Micro;

use Neutrino\Constants\Events;
use Neutrino\Interfaces\Middleware\AfterInterface;
use Neutrino\Interfaces\Middleware\BeforeInterface;
use Phalcon\Di\Injectable;
use Phalcon\Events\Event;
use Phalcon\Mvc\Micro;
use Phalcon\Mvc\Micro\Collection;

/**
 * Class Router
 *
 * @property \Phalcon\Mvc\Micro $application
 * @property \Phalcon\Mvc\Router $router
 *
 * @package Neutrino\Micro
 */
class Router extends Injectable implements RouterInterface
{
    /**
     * @deprecated Micro Application doesn't support modules.
     *
     * Sets the name of the default module
     *
     * @param string $moduleName
     */
    public function setDefaultModule($moduleName)
    {
        throw new \RuntimeException(__CLASS__ . ' doesn\'t support modules.');
    }

    /**
     * @deprecated Micro Application doesn't support default controller.
     *
     * Sets the default controller name
     *
     * @param string $controllerName
     */
    public function setDefaultController($controllerName)
    {
        throw new \RuntimeException(__CLASS__ . ' doesn\'t support default controller.');
    }

    /**
     * @deprecated Micro Application doesn't support default action.
     *
     * Sets the default action name
     *
     * @param string $actionName
     */
    public function setDefaultAction($actionName)
    {
        throw new \RuntimeException(__CLASS__ . ' doesn\'t support default action.');
    }

    /**
     * @deprecated Micro Application doesn't support default paths.
     *
     * Sets an array of default paths
     *
     * @param array $defaults
     */
    public function setDefaults(array $defaults)
    {
        throw new \RuntimeException(__CLASS__ . ' doesn\'t support defaults paths.');
    }

    /**
     * Handles routing information received from the rewrite engine
     *
     * @param string $uri
     */
    public function handle($uri = null)
    {
        $this->router->handle($uri);
    }

    /**
     * Adds a route to the router on any HTTP method
     *
     * @param string $pattern
     * @param mixed  $paths
     * @param mixed  $httpMethods
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function add($pattern, $paths = null, $httpMethods = null)
    {
        foreach ($httpMethods as $httpMethod) {
            $this->application->{strtolower($httpMethod)}($pattern, $this->pathToHandler($paths));
        }

        return null;
    }

    /**
     * Adds a route to the router that only match if the HTTP method is GET
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addGet($pattern, $paths = null)
    {
        return $this->application->get($pattern, $this->pathToHandler($paths));
    }

    /**
     * Adds a route to the router that only match if the HTTP method is POST
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addPost($pattern, $paths = null)
    {
        return $this->application->post($pattern, $this->pathToHandler($paths));
    }

    /**
     * Adds a route to the router that only match if the HTTP method is PUT
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addPut($pattern, $paths = null)
    {
        return $this->application->put($pattern, $this->pathToHandler($paths));
    }

    /**
     * Adds a route to the router that only match if the HTTP method is PATCH
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addPatch($pattern, $paths = null)
    {
        return $this->application->patch($pattern, $this->pathToHandler($paths));
    }

    /**
     * Adds a route to the router that only match if the HTTP method is DELETE
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addDelete($pattern, $paths = null)
    {
        return $this->application->delete($pattern, $this->pathToHandler($paths));
    }

    /**
     * Add a route to the router that only match if the HTTP method is OPTIONS
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addOptions($pattern, $paths = null)
    {
        return $this->application->options($pattern, $this->pathToHandler($paths));
    }

    /**
     * Adds a route to the router that only match if the HTTP method is HEAD
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addHead($pattern, $paths = null)
    {
        return $this->application->head($pattern, $this->pathToHandler($paths));
    }

    /**
     * @deprecated Micro Application doesn't support HTTP PURGE method.
     *
     * Adds a route to the router that only match if the HTTP method is PURGE (Squid and Varnish support)
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addPurge($pattern, $paths = null)
    {
        throw new \RuntimeException(__METHOD__ . ': Micro Application doesn\'t support HTTP PURGE method.');
    }

    /**
     * @deprecated Micro Application doesn't support HTTP TRACE method.
     *
     * Adds a route to the router that only match if the HTTP method is TRACE
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addTrace($pattern, $paths = null)
    {
        throw new \RuntimeException(__METHOD__ . ': Micro Application doesn\'t support HTTP TRACE method.');
    }

    /**
     * @deprecated Micro Application doesn't support HTTP CONNECT method.
     *
     * Adds a route to the router that only match if the HTTP method is CONNECT
     *
     * @param string $pattern
     * @param mixed  $paths
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function addConnect($pattern, $paths = null)
    {
        throw new \RuntimeException(__METHOD__ . ': Micro Application doesn\'t support HTTP CONNECT method.');
    }

    /**
     * Adds a notFound route
     *
     * @param callable $handler
     */
    public function notFound($handler)
    {
        $this->application->notFound($handler);
    }

    /**
     * Mounts a group of routes in the router
     *
     * @param \Phalcon\Mvc\Micro\Collection $collection
     *
     * @return RouterInterface
     */
    public function mount(Collection $collection)
    {
        $this->application->mount($collection);

        return $this;
    }

    /**
     * @deprecated Micro Application doesn't support clear method.
     *
     * Removes all the defined routes
     */
    public function clear()
    {
        throw new \RuntimeException(__METHOD__ . ': you can\'t clear the router in micro application.');
    }

    /**
     * @deprecated Micro Application doesn't support modules.
     *
     * Returns processed module name
     *
     * @return string
     */
    public function getModuleName()
    {
        throw new \RuntimeException(__METHOD__ . ' doesn\'t support modules.');
    }

    /**
     * Returns processed namespace name
     *
     * @return string
     */
    public function getNamespaceName()
    {
        return $this->router->getNamespaceName();
    }

    /**
     * Returns processed controller name
     *
     * @return string
     */
    public function getControllerName()
    {
        return $this->router->getControllerName();
    }

    /**
     * Returns processed action name
     *
     * @return string
     */
    public function getActionName()
    {
        return $this->router->getActionName();
    }

    /**
     * Returns processed extra params
     *
     * @return array
     */
    public function getParams()
    {
        return $this->router->getParams();
    }

    /**
     * Returns the route that matches the handled URI
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function getMatchedRoute()
    {
        return $this->router->getMatchedRoute();
    }

    /**
     * Return the sub expressions in the regular expression matched
     *
     * @return array
     */
    public function getMatches()
    {
        return $this->router->getMatches();
    }

    /**
     * Check if the router matches any of the defined routes
     *
     * @return bool
     */
    public function wasMatched()
    {
        return $this->router->wasMatched();
    }

    /**
     * Return all the routes defined in the router
     *
     * @return \Phalcon\Mvc\Router\RouteInterface[]
     */
    public function getRoutes()
    {
        return $this->router->getRoutes();
    }

    /**
     * Returns a route object by its id
     *
     * @param mixed $id
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function getRouteById($id)
    {
        return $this->router->getRouteById($id);
    }

    /**
     * Returns a route object by its name
     *
     * @param string $name
     *
     * @return \Phalcon\Mvc\Router\RouteInterface
     */
    public function getRouteByName($name)
    {
        return $this->router->getRouteByName($name);
    }

    /**
     * @param $path
     *
     * @return \Closure
     */
    protected function pathToHandler($path){
        if ($path instanceof \Closure) {
            return $path;
        }

        if (is_array($path)) {
            return function (...$args) use ($path) {
                /** @var Micro $this */

                $controller = isset($path['controller']) ? $path['controller'] : null;
                $action = isset($path['action']) ? $path['action'] : null;

                $handler = $this->getDI()->get($controller);

                if (!method_exists($handler, $action)) {
                    throw new \RuntimeException('Method : "' . $action . '" doesn\'t exist on "' . $controller . '"');
                }

                if (isset($path['middlewares'])) {
                    foreach ($path['middlewares'] as $middleware => $params) {
                        if (is_string($params)) {
                            $middleware = $params;
                            $params = [];
                        }

                        /** @var \Neutrino\Foundation\Middleware\Controller $middleware */
                        $middlewares[] = $middleware = new $middleware($controller, ...$params);

                        if ($middleware instanceof BeforeInterface) {
                            if (!isset($event)) {
                                $event = new Event(Events\Micro::BEFORE_EXECUTE_ROUTE, $this);
                            }

                            $result = $middleware->before($event, $this, null);

                            if ($result === false) {
                                return $this->response;
                            }
                        }
                    }
                }

                $value = $handler->$action(...$args);

                if (isset($middlewares)) {
                    $event = null;
                    foreach ($middlewares as $middleware) {
                        if ($middleware instanceof AfterInterface) {
                            if (!isset($event)) {
                                $event = new Event(Events\Micro::AFTER_EXECUTE_ROUTE, $this);
                            }

                            $middleware->after($event, $this, null);
                        }
                    }
                }

                return $value;
            };
        }

        throw new \RuntimeException("invalid route paths");
    }
}


<?php

namespace Igniter\Flame\Pagic;

use Exception;
use Symfony\Component\Debug\Exception\FatalThrowableError;
use Throwable;

class Template
{
    private $env;

    protected $path;

    protected $page;

    protected $layout;

    protected $theme;

    protected $param;

    protected $controller;

    protected $session;

    /**
     * This method is for internal use only and should never be called
     * directly (use Environment::load() instead).
     * @internal
     *
     * @param \Igniter\Flame\Pagic\Environment $env
     * @param $path
     */
    public function __construct(Environment $env, $path)
    {
        $this->env = $env;
        $this->path = $path;
    }

    /**
     * Renders the template.
     *
     * @param array $context An array of parameters to pass to the template
     *
     * @return string The rendered template
     * @throws \Exception
     * @throws \Throwable
     */
    public function render($context = [])
    {
        $this->mergeGlobals($context);

        unset($context['this']);

        $obLevel = ob_get_level();
        ob_start();

        extract($context);

        // We'll evaluate the contents of the view inside a try/catch block so we can
        // flush out any stray output that might get out before an error occurs or
        // an exception is thrown. This prevents any partial views from leaking.
        try {
            $filePath = $this->path;
            include $filePath;
        }
        catch (Exception $e) {
            $this->handleException($e, $obLevel);
        }
        catch (Throwable $e) {
            $this->handleException(new FatalThrowableError($e), $obLevel);
        }

        return ob_get_clean();
    }

    protected function mergeGlobals($context)
    {
        if (array_key_exists('this', $context)) {
            foreach ($context['this'] as $key => $object) {
                if (property_exists($this, $key))
                    $this->{$key} = $object;
            }
        }
    }

    protected function handleException($ex, $level)
    {
        while (ob_get_level() > $level) {
            ob_end_clean();
        }

        throw $ex;
    }
}


<?php

namespace Igniter\Flame\Pagic\Source;

class SourceResolver implements SourceResolverInterface
{
    /**
     * All of the registered sources.
     *
     * @var array
     */
    protected $sources = [];

    /**
     * The default source name.
     *
     * @var string
     */
    protected $default;

    /**
     * Create a new source resolver instance.
     *
     * @param  array $sources
     */
    public function __construct(array $sources = [])
    {
        foreach ($sources as $name => $source) {
            $this->addSource($name, $source);
        }
    }

    /**
     * Get a source instance.
     *
     * @param  string $name
     *
     * @return \Igniter\Flame\Pagic\Source\SourceInterface
     */
    public function source($name = null)
    {
        if (is_null($name)) {
            $name = $this->getDefaultSourceName();
        }

        return $this->sources[$name];
    }

    /**
     * Add a source to the resolver.
     *
     * @param  string $name
     * @param \Igniter\Flame\Pagic\Source\SourceInterface $source
     *
     * @return void
     */
    public function addSource($name, SourceInterface $source)
    {
        $this->sources[$name] = $source;
    }

    /**
     * Check if a source has been registered.
     *
     * @param  string $name
     *
     * @return bool
     */
    public function hasSource($name)
    {
        return isset($this->sources[$name]);
    }

    /**
     * Get the default source name.
     * @return string
     */
    public function getDefaultSourceName()
    {
        return $this->default;
    }

    /**
     * Set the default source name.
     *
     * @param  string $name
     *
     * @return void
     */
    public function setDefaultSourceName($name)
    {
        $this->default = $name;
    }
}


<?php

namespace Neutrino\HttpClient\Provider\StreamContext;

use Neutrino\HttpClient\Contract\Streaming\Streamable;
use Neutrino\HttpClient\Contract\Streaming\Streamize;
use Neutrino\HttpClient\Provider\StreamContext;

/**
 * Class Streaming
 *
 * @package Neutrino\HttpClient\Provider\StreamContext
 */
class Streaming extends StreamContext implements Streamable
{
    use Streamize;

    /**
     * @param $context
     *
     * @return bool
     */
    protected function streamContextExec($context)
    {
        $emitter = $this->getEventsManager();

        try {
            $handler = fopen($this->uri->build(), 'r', null, $context);

            $this->streamContextParseHeader($http_response_header);

            $this->response->setProviderDatas(stream_get_meta_data($handler));

            $emitter->fire(self::EVENT_START, $this);

            $buffer = $this->bufferSize ? $this->bufferSize : 4096;

            while (!feof($handler)) {
                $emitter->fire(self::EVENT_PROGRESS, $this, stream_get_contents($handler, $buffer));
            }

            $this->response->setProviderDatas(stream_get_meta_data($handler));

            $emitter->fire(self::EVENT_FINISH, $this);

            return true;
        } finally {
            if (isset($handler) && is_resource($handler)) {
                fclose($handler);
            }
        }
    }
}