<?php

namespace Neutrino;

use Phalcon\Db\Column;
use Phalcon\Mvc\Model\Behavior\SoftDelete;
use Phalcon\Mvc\Model\Behavior\Timestampable;
use Phalcon\Mvc\Model\MetaData;

/**
 * Class Model
 *
 *  @package Neutrino
 */
abstract class Model extends \Phalcon\Mvc\Model
{
    /**
     * @var array
     */
    protected static $metaDatasClass = [];

    /**
     * @var array
     */
    protected static $columnsMapClass = [];

    /**
     * Initializes metaDatas & columnsMap if they are not.
     */
    public function initialize()
    {
        static::$metaDatasClass[static::class] = [
            MetaData::MODELS_ATTRIBUTES               => [],
            MetaData::MODELS_PRIMARY_KEY              => [],
            MetaData::MODELS_NON_PRIMARY_KEY          => [],
            MetaData::MODELS_NOT_NULL                 => [],
            MetaData::MODELS_DATA_TYPES               => [],
            MetaData::MODELS_DATA_TYPES_NUMERIC       => [],
            MetaData::MODELS_DATE_AT                  => [],
            MetaData::MODELS_DATE_IN                  => [],
            MetaData::MODELS_IDENTITY_COLUMN          => false,
            MetaData::MODELS_DATA_TYPES_BIND          => [],
            MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => [],
            MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => [],
            MetaData::MODELS_DEFAULT_VALUES           => [],
            MetaData::MODELS_EMPTY_STRING_VALUES      => []
        ];
    }

    /**
     * Return the metaData
     *
     * @return array
     */
    public function metaData()
    {
        return static::$metaDatasClass[static::class];
    }

    /**
     * Return the columnMap
     *
     * @return array
     */
    public function columnMap()
    {
        return static::$columnsMapClass[static::class];
    }

    /**
     * Define the primary column
     *
     * @param string $name
     * @param int    $type
     * @param array  $options
     */
    protected function primary($name, $type, array $options = [])
    {
        static::addColumn($name, $type, isset($options['map']) ? $options['map'] : $name);

        static::$metaDatasClass[static::class][MetaData::MODELS_PRIMARY_KEY][] = $name;
        static::$metaDatasClass[static::class][MetaData::MODELS_NOT_NULL][] = $name;

        if (
            (!isset($options['identity']) || $options['identity']) &&
            (!isset($options['multiple']) || !$options['multiple'])
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_IDENTITY_COLUMN] = $name;
        }
        if (
            (!isset($options['autoIncrement']) || $options['autoIncrement']) &&
            (!isset($options['multiple']) || !$options['multiple'])
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT][$name] = true;
        }
    }

    /**
     * Define a column
     *
     * @param string $name
     * @param int    $type
     * @param array  $options
     */
    protected function column($name, $type, array $options = [])
    {
        static::addColumn($name, $type, isset($options['map']) ? $options['map'] : $name);

        static::$metaDatasClass[static::class][MetaData::MODELS_NON_PRIMARY_KEY][] = $name;

        if (isset($options['nullable']) && $options['nullable']) {
            static::$metaDatasClass[static::class][MetaData::MODELS_EMPTY_STRING_VALUES][$name] = true;
        } else {
            static::$metaDatasClass[static::class][MetaData::MODELS_NOT_NULL][] = $name;
        }

        if (isset($options['default'])) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DEFAULT_VALUES][$name] = $options['default'];
        }

        if (isset($options['autoInsert']) && $options['autoInsert']) {
            static::$metaDatasClass[static::class][MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT][$name] = true;
        }

        if (isset($options['autoUpdate']) && $options['autoUpdate']) {
            static::$metaDatasClass[static::class][MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE][$name] = true;
        }
    }

    /**
     * Define a timestampable column.
     * Automatically add the Timestampable behavior.
     *
     * @param string $name
     * @param array  $options
     */
    protected function timestampable($name, array $options = [])
    {
        if ((isset($options['autoInsert']) && $options['autoInsert']) ||
            (isset($options['autoUpdate']) && $options['autoUpdate'])
        ) {
            throw new \RuntimeException('Model: A timestampable field can\'t have autoInsert or autoUpdate.');
        }

        self::column($name, isset($options['type']) ? $options['type'] : Column::TYPE_DATETIME, $options);

        $params = [];

        if (!isset($options['default']) && isset($options['insert']) && $options['insert']) {
            $params['beforeValidationOnCreate'] = [
                'field'  => $name,
                'format' => isset($options['format']) ? $options['format'] : DATE_ATOM
            ];
        }

        if (isset($options['update']) && $options['update']) {
            $params['beforeValidationOnUpdate'] = [
                'field'  => $name,
                'format' => isset($options['format']) ? $options['format'] : DATE_ATOM
            ];
        }

        if(empty($params)){
            throw new \RuntimeException('Model: A timestampable field needs to have at least insert or update.');
        }

        $this->addBehavior(new Timestampable($params));
    }

    /**
     * Add <created_at> & <updated_at> columns with  Timestampable behavior.
     */
    protected function timestamps()
    {
        $this->timestampable('created_at', ['insert' => true]);
        $this->timestampable('updated_at', ['update' => true]);
    }

    /**
     * Define a softDeleted column.
     * Automatically add the SoftDelete behavior.
     *
     * @param string $name
     * @param array  $options
     */
    protected function softDeletable($name, array $options = [])
    {
        if ((isset($options['autoInsert']) && $options['autoInsert']) ||
            (isset($options['autoUpdate']) && $options['autoUpdate'])
        ) {
            throw new \RuntimeException('Model: A timestampable field can\'t have autoInsert or autoUpdate.');
        }

        self::column($name, isset($options['type']) ? $options['type'] : Column::TYPE_BOOLEAN, $options);

        $this->addBehavior(new SoftDelete([
            'field' => $name,
            'value' => isset($options['value']) ? $options['value'] : true
        ]));
    }

    /**
     * Add <deleted> column with SoftDelete behavior.
     */
    protected function softDelete()
    {
        $this->softDeletable('deleted');
    }

    /**
     * Add column type
     *
     * @param string $name
     * @param int    $type
     * @param string $map
     */
    private static function addColumn($name, $type, $map)
    {
        static::$columnsMapClass[static::class][$name] = $map;

        static::$metaDatasClass[static::class][MetaData::MODELS_ATTRIBUTES][] = $name;
        static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES][$name] = $type;

        static::describeColumnType($name, $type);
    }

    /**
     * Define a column type
     *
     * @param string $name
     * @param int    $type
     */
    private static function describeColumnType($name, $type)
    {
        if ($type === null) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_NULL;
        } elseif (
            $type === Column::TYPE_BIGINTEGER ||
            $type === Column::TYPE_INTEGER ||
            $type === Column::TYPE_TIMESTAMP
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_INT;
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_NUMERIC][$name] = true;
        } elseif (
            $type === Column::TYPE_DECIMAL ||
            $type === Column::TYPE_FLOAT ||
            $type === Column::TYPE_DOUBLE
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_DECIMAL;
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_NUMERIC][$name] = true;
        } elseif (
            $type === Column::TYPE_JSON ||
            $type === Column::TYPE_TEXT ||
            $type === Column::TYPE_CHAR ||
            $type === Column::TYPE_VARCHAR ||
            $type === Column::TYPE_DATE ||
            $type === Column::TYPE_DATETIME
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_STR;
        } elseif (
            $type === Column::TYPE_BLOB ||
            $type === Column::TYPE_JSONB ||
            $type === Column::TYPE_MEDIUMBLOB ||
            $type === Column::TYPE_TINYBLOB ||
            $type === Column::TYPE_LONGBLOB
        ) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_BLOB;
        } elseif ($type === Column::TYPE_BOOLEAN) {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_PARAM_BOOL;
        } else {
            static::$metaDatasClass[static::class][MetaData::MODELS_DATA_TYPES_BIND][$name] = Column::BIND_SKIP;
        }
    }
}


<?php

namespace Igniter\Flame\Geolite;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;

class GeoliteServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = TRUE;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->mergeConfigFrom(
            __DIR__.'/config/geocoder.php', 'geocoder'
        );

        $this->app->singleton('geocoder', function ($app) {
            return new Geocoder($app);
        });

        $this->app->singleton('geolite', function () {
            return new Geolite;
        });

        $aliasLoader = AliasLoader::getInstance();
        $aliasLoader->alias('Geocoder', Facades\Geocoder::class);
        $aliasLoader->alias('Geolite', Facades\Geolite::class);
    }

    /**
     * Get the services provided by the provider.
     * @return array
     */
    public function provides()
    {
        return [
            'geocoder', Geocoder::class,
            'geolite', Geolite::class
        ];
    }
}


<?php

namespace Igniter\Flame\Foundation\Bootstrap;

use Igniter\Flame\Translation\FileLoader;
use Igniter\Flame\Translation\Localization;
use Igniter\Flame\Translation\Translator;
use Illuminate\Contracts\Foundation\Application;

class LoadTranslation
{
    /**
     * Register Auto Loader
     *
     * @param  \Illuminate\Contracts\Foundation\Application $app
     *
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $app->singleton('translation.loader', function ($app) {
            return new FileLoader($app['files'], $app['path.lang']);
        });

        $app->singleton('translator', function ($app) {
            $loader = $app['translation.loader'];

            // When registering the translator component, we'll need to set the default
            // locale as well as the fallback locale. So, we'll grab the application
            // configuration so we can easily get both of these values from there.
            $locale = $app['config']['app.locale'];

            $trans = new Translator($loader, $locale);

            $trans->setFallback($app['config']['app.fallback_locale']);

            return $trans;
        });

        $app->singleton('translator.localization', function ($app) {
            $locale = $app['config']['app.locale'];
            $config['supportedLocales'] = setting('supported_languages', []);
            $config['detectBrowserLocale'] = setting('detect_language', []);

            return new Localization($app['request'], $locale, $config);
        });
    }
}


<?php

namespace Neutrino\Cli;

use Neutrino\Cli\Output\Block;
use Neutrino\Cli\Output\QuestionHelper;
use Neutrino\Cli\Output\Table;
use Neutrino\Cli\Question\ChoiceQuestion;
use Neutrino\Cli\Question\ConfirmationQuestion;
use Neutrino\Cli\Question\Question;
use Neutrino\Support\Arr;
use Phalcon\Cli\Router\Route;
use Phalcon\Cli\Task as PhalconTask;

/**
 * Class Task
 *
 * @package Neutrino\Cli
 *
 * @property-read \Neutrino\Foundation\Cli\Kernel        $application
 * @property-read \Phalcon\Config|\stdClass|\ArrayAccess $config
 * @property-read \Neutrino\Cli\Router                   $router
 * @property-read \Phalcon\Cli\Dispatcher                $dispatcher
 * @property-read \Neutrino\Cli\Output\Writer            $output
 */
abstract class Task extends PhalconTask
{
    protected $options;

    protected $arguments;

    protected function onConstruct()
    {
        $this->applyArguments();
        $this->applyOptions();
    }

    protected function applyOptions()
    {
        $this->options = $this->dispatcher->getOptions();
    }

    protected function applyArguments()
    {
        $args = $this->dispatcher->getParams();

        $this->arguments = is_string($args) ? explode(Route::getDelimiter(), $args) : $args;
    }

    /**
     * @param string $task
     * @param string $action
     * @param array  $args
     * @param array  $opts
     */
    public function callTask($task, $action, $args = [], $opts = [])
    {
        $handler = [
            'task'   => $task,
            'action' => $action,
        ];

        $options = [];
        foreach ($opts as $name => $opt) {
            if ($opt === true) {
                $options[] = "-$name";
            } else {
                $options[] = "--$name=$opt";
            }
        }

        $this->application->handle(array_merge(
            $handler,
            $args,
            $options
        ));
    }

    /**
     * @param string $str
     */
    public function line($str)
    {
        $this->output->write($str, true);
    }

    /**
     * @param string $str
     */
    public function info($str)
    {
        $this->output->info($str);
    }

    /**
     * @param string $str
     */
    public function notice($str)
    {
        $this->output->notice($str);
    }

    /**
     * @param string $str
     */
    public function warn($str)
    {
        $this->output->warn($str);
    }

    /**
     * @param string $str
     */
    public function error($str)
    {
        $this->output->error($str);
    }

    /**
     * @param string $str
     */
    public function question($str)
    {
        $this->output->question($str);
    }

    /**
     * @param string      $str
     * @param null|string $default
     *
     * @return null|string
     */
    public function prompt($str, $default = null)
    {
        return $this->ask(new Question($str, $default));
    }

    /**
     * @param string $str
     * @param bool   $default
     *
     * @return null|string
     */
    public function confirm($str, $default = false)
    {
        return $this->ask(new ConfirmationQuestion($str, $default));
    }

    /**
     * @param string      $str
     * @param array       $choices
     * @param int         $maxAttempts
     * @param null|string $default
     *
     * @return null|string
     */
    public function choices($str, array $choices, $default = null, $maxAttempts = null)
    {
        return $this->ask(new ChoiceQuestion($str, $choices, $default, $maxAttempts));
    }

    /**
     * @param \Neutrino\Cli\Question\Question $question
     *
     * @return null|string
     */
    public function ask(Question $question)
    {
        return QuestionHelper::ask($this->output, STDIN, $question);
    }

    /**
     * @param array $datas
     * @param array $headers
     * @param int   $style Table::STYLE_DEFAULT | Table::NO_STYLE | ...
     */
    public function table(array $datas, array $headers = [], $style = Table::STYLE_DEFAULT)
    {
        (new Table($this->output, $datas, $headers, $style))->display();
    }

    /**
     * @param array  $lines
     * @param string $style Output function used to display block (notice, info, warn, ...)
     * @param int    $padding
     */
    public function block($lines, $style, $padding = 4)
    {
        (new Block($this->output, $style, ['padding' => $padding]))->draw($lines);
    }

    /**
     * Return all agruments pass to the cli
     *
     * @return array
     */
    protected function getArgs()
    {
        return $this->arguments;
    }

    /**
     * Return an arg by his name, or default
     *
     * @param string     $name
     * @param mixed|null $default
     *
     * @return string|null
     */
    protected function getArg($name, $default = null)
    {
        return Arr::fetch($this->arguments, $name, $default);
    }

    /**
     * Check if arg has been passed
     *
     * @param string $name
     *
     * @return bool
     */
    protected function hasArg($name)
    {
        return Arr::has($this->arguments, $name);
    }

    /**
     * Return all options pass to the cli
     *
     * @return array
     */
    protected function getOptions()
    {
        return $this->options;
    }

    /**
     * Return an option by his name, or default
     *
     * @param string     $name
     * @param mixed|null $default
     *
     * @return string|null
     */
    protected function getOption($name, $default = null)
    {
        return Arr::fetch($this->options, $name, $default);
    }

    /**
     * Check if option has been passed
     *
     * @param string[] ...$options
     *
     * @return bool
     */
    protected function hasOption(...$options)
    {
        foreach ($options as $option) {
            if (Arr::has($this->options, $option)) {
                return true;
            }
        }

        return false;
    }
}


<?php namespace Fbf\LaravelCategories;

use Baum\Node;

/**
 * Category
 */
class Category extends Node {

	/**
	 * Status values for the database
	 */
	const DRAFT = 'DRAFT';
	const APPROVED = 'APPROVED';

	/**
	 * Table name.
	 *
	 * @var string
	 */
	protected $table = 'fbf_categories';

	/**
	 * Used for Cviebrock/EloquentSluggable
	 * @var array
	 */
	public static $sluggable = array(
		'build_from' => 'name',
		'save_to' => 'slug',
		'separator' => '-',
		'unique' => true,
		'include_trashed' => true,
	);

	/**
	 * Stores the old parent id before editing
	 * @var integer
	 */
	protected $oldParentId = null;

	/**
	 * The "booting" method of the model.
	 *
	 * @return void
	 */
	protected static function boot() {

		parent::boot();

		static::updating(function ($category) {

			// Baum triggers a parent move, which puts the item last in the list, even if the old and new parents are the same
			if ($category->isParentIdSame())
			{
				$category->stopBaumParentMove();
			}

		});

	}

	/**
	 * Returns true if the parent_id value in the database is different to the current value in the model's dirty attributes
	 * @return bool
	 */
	protected function isParentIdSame()
	{
		$dirty = $this->getDirty();
		$oldNavItem = self::where('id','=',$this->id)->first();
		$oldParent = $oldNavItem->parent;
		$oldParentId = $oldParent->id;
		$isParentColumnSet = isset($dirty[$this->getParentColumnName()]);
		if ($isParentColumnSet)
		{
			$isNewParentSameAsOld = $dirty[$this->getParentColumnName()] == $oldParentId;
		}
		else
		{
			$isNewParentSameAsOld = false;
		}
		return $isParentColumnSet && $isNewParentSameAsOld;
	}

	/**
	 * Removes the parent_id field from the model's attributes and sets $moveToNewParentId static property on the parent
	 * Baum\Node model class to false to prevent Baum from triggering a move. This can be required because Baum triggers
	 * a parent move, which puts the item last in the list, even if the old and new parents are the same.
	 */
	protected function stopBaumParentMove()
	{
		unset($this->{$this->getParentColumnName()});
		static::$moveToNewParentId = FALSE;
	}

	/**
	 * Adds a query scope to add conditions to query object
	 *
	 * @param $query
	 * @return mixed
	 */
	public function scopeLive($query)
	{
		return $query->where('status', '=', self::APPROVED)
			->where('published_date', '<=', \Carbon\Carbon::now());
	}

	/**
	 * Accessor for path attribute, which is a string consisting of the ancestors of each node, separated by " > ".
	 * @return string
	 */
	public function getPathAttribute()
	{
		$ancestors = $this->getAncestors();
		$return = array();
		foreach($ancestors as $ancestor) {
			$return[] = $ancestor->name;
		}
		$return[] = $this->name;
		return implode(' > ', $return);
	}

}


<?php

namespace Neutrino\Providers;

use Neutrino\Constants\Services;
use Neutrino\Support\Provider;

/**
 * Class Crypt
 *
 *  @package Neutrino\Providers
 */
class Crypt extends Provider
{
    protected $class = \Phalcon\Crypt::class;

    protected $name = Services::CRYPT;

    protected $shared = true;

    protected $aliases = [\Phalcon\Crypt::class];

    /**
     * Return the service to register
     *
     * Called when the services container tries to resolve the service
     *
     * @return mixed
     */
    protected function register()
    {
        $app = $this->config->app;

        $crypt = new \Phalcon\Crypt($app->cipher);

        $crypt->setKey($app->key);

        return $crypt;
    }
}


<?php

namespace Neutrino\Assets;

use Neutrino\Assets\Exception\CompilatorException;
use Neutrino\Http\Standards\Method;
use Neutrino\HttpClient\Factory;
use Neutrino\HttpClient\Parser\JsonArray;

/**
 * Class JsCompiler
 *
 * Neutrino\Assets
 */
class ClosureCompiler implements AssetsCompilator
{

    /**
     * @param array $options
     *
     * @return mixed
     * @throws CompilatorException
     * @throws \Exception
     */
    public function compile(array $options)
    {
        $jsCode = $this->extractJsCode($options['compile']['directories']);
        $jsCode = $this->applyPrecompilation($jsCode, isset($options['precompilations']) ? $options['precompilations'] : []);

        $data = [
          'compilation_level' => $options['compile']['level'],
          'output_format' => 'json',
          'output_info' => ['warnings', 'errors', 'statistics', 'compiled_code'],
          'warning_level' => 'default',
        ];

        if (!empty($options['compile']['externs_url'])) {
            $data['externs_url'] = $options['compile']['externs_url'];
        }

        if (!empty($options['compile']['js_externs'])) {
            $data['js_externs'] = $this->extractJsCode($options['compile']['js_externs']);
        }

        $query = http_build_query(['js_code' => $jsCode]) . '&' . preg_replace('/%5B[0-9]+%5D/simU', '', http_build_query($data));

        $request = Factory::makeRequest();
        $request
            ->setMethod(Method::POST)
            ->setUri('https://closure-compiler.appspot.com/compile')
            ->setParams($query)
            ->disableSsl();

        $response = $request->send();

        if (!$response->isOk()) {
            throw new CompilatorException(
                "Can't call closure compile api.\n" .
                "HTTP Status : {$response->getHeader()->get('Status')}\n" .
                "HTTP Erreur : [{$response->getErrorCode()}]: {$response->getError()}\n" .
                "HTTP Body   : {$response->getBody()}"
            );
        }

        $content = $response->parse(JsonArray::class)->getData();

        file_put_contents(BASE_PATH . '/' . $options['output_file'], $content['compiledCode']);

        unset($content['compiledCode']);

        return $content;
    }

    private function applyPrecompilation($content, array $precompilators)
    {
        foreach ($precompilators as $precompilator => $options) {
            if (is_string($options)) {
                $precompilator = $options;
                $options = [];
            }

            /** @var \Neutrino\Assets\Closure\Precompilation $precompilator */
            $precompilator = new $precompilator($options);

            $content = $precompilator->precompile($content);
        }

        return $content;
    }

    private function extractJsCode(array $directories)
    {
        $content = [];

        foreach ($directories as $directory) {
            foreach ($this->getDirFiles(BASE_PATH . '/' . $directory) as $item) {
                if (is_file($item)) {
                    $content[] = file_get_contents($item);
                }
            }
        }

        return implode(';', $content);
    }

    private function getDirFiles($path)
    {
        $files = [];

        $paths = glob($path . '/*');

        usort($paths, function ($a, $b) {
            if (is_file($a)) {
                return -1;
            }
            if (is_file($b)) {
                return 1;
            }
            return 0;
        });

        foreach ($paths as $item) {
            if (is_dir($item)) {
                $files = array_merge($files, $this->getDirFiles($item));
            } elseif (is_file($item)) {
                $files[] = $item;
            }
        }

        return $files;
    }
}


<?php

namespace Neutrino\Foundation\Cli\Tasks;

use Neutrino\Cli\Output\Decorate;
use Neutrino\Cli\Task;
use Neutrino\Config\ConfigPreloader;

/**
 * Class ConfigCacheTask
 *
 * @package     Neutrino\Foundation\Cli\Tasks
 */
class ConfigCacheTask extends Task
{

    /**
     * Configuration cache.
     *
     * @description Cache the configuration.
     *
     * @throws \Exception
     */
    public function mainAction()
    {
        $this->output->write(Decorate::notice(str_pad('Generating configuration cache', 40, ' ')), false);

        $preloader = new ConfigPreloader();

        try {
            $preloader->compile();

            $this->info("Success");
        } catch (\Exception $e) {
            $this->error("Error");
            $this->block([$e->getMessage()], 'error');
        }
    }
}


<?php

namespace Neutrino\Database\Schema\Dialect;

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

/**
 * Trait MysqlTrait
 *
 * @package Neutrino\Database\Schema\Dialect
 */
trait MysqlTrait
{
    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 FOREIGN_KEY_CHECKS=1;';
    }

    /**
     * Get SQL Disable foreign key constraints.
     *
     * @return string
     */
    public function disableForeignKeyConstraints()
    {
        return 'SET FOREIGN_KEY_CHECKS=0;';
    }

    /**
     * @param \Neutrino\Support\Fluent $column
     * @param string                   $type
     *
     * @return string
     */
    protected function compileTimableColumn(Fluent $column, $type)
    {
        $precision = !empty($column['precision']) ? '(' . $column['precision'] . ')' : '';

        $type .= $precision;

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

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

        if (!empty($column['onUpdate'])) {
            $type .= ' ON UPDATE ' . $column['onUpdate'] . $precision;

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

        return $type;
    }

    /**
     * Create the column type definition for a dateTimeTz type.
     *
     * @param \Neutrino\Support\Fluent $column
     *
     * @return array
     */
    public function typeTime(Fluent $column)
    {
        if (!empty($column['precision'])) {
            if (isset($column['onUpdate'])) {
                unset($column['onUpdate']);
            }

            if (isset($column['default']) && $column['default'] === 'CURRENT_TIMESTAMP') {
                unset($column['default']);
            }

            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']) || !empty($column['onUpdate'])) {
            return [
                'type' => $this->compileTimableColumn($column, 'DATETIME'),
                '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']) || !empty($column['onUpdate'])) {
            return [
                'type' => $this->compileTimableColumn($column, 'TIMESTAMP'),
                'typeReference' => Column::TYPE_TIMESTAMP
            ];
        }

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

    /**
     * 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 "RENAME TABLE " . $this->prepareTable($from, $schema) . " TO " . $this->prepareTable($to, $schema);
    }
}


<?php

namespace Igniter\Flame\Database\Traits;

use Exception;
use Igniter\Flame\Database\PermalinkMaker;
use Model;

/**
 * HasPermalink model trait
 * Usage:
 **
 * In the model class definition:
 *   use \Igniter\Flame\Database\Traits\HasPermalink;
 * You can change the slug field used by declaring:
 *   protected $permalink = ['permalink_slug' => ['source' => 'name']];
 */
trait HasPermalink
{
    /**
     * Boot the sortable trait for this model.
     * @return void
     * @throws \Exception
     */
    public static function bootHasPermalink()
    {
        if (!property_exists(get_called_class(), 'permalinkable')) {
            throw new Exception(sprintf(
                'You must define a $permalinkable property in %s to use the HasPermalink trait.', get_called_class()
            ));
        }

        static::saving(function (Model $model) {
            $model->generatePermalinkOnSave();
        });
    }

    /**
     * Handle adding permalink slug on model update.
     */
    protected function generatePermalinkOnSave()
    {
        $this->getPermalinkMaker()->slug($this);
    }

    /**
     * Primary slug column of this model.
     * @return string
     */
    public function getSlugKeyName()
    {
        if (property_exists($this, 'slugKeyName')) {
            return $this->slugKeyName;
        }

        $config = $this->permalinkable();
        $name = reset($config);
        $key = key($config);

        // check for short configuration
        if ($key === 0) {
            return $name;
        }

        return $key;
    }

    /**
     * Primary slug value of this model.
     * @return string
     */
    public function getSlugKey()
    {
        return $this->getAttribute($this->getSlugKeyName());
    }

    /**
     * Query scope for finding a model by its primary slug.
     *
     * @param $query
     * @param string $slug
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeWhereSlug($query, $slug)
    {
        return $query->where($this->getSlugKeyName(), $slug);
    }

    /**
     * Query scope for finding "similar" slugs, used to determine uniqueness.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $attribute
     * @param array $config
     * @param string $slug
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeFindSimilarSlugs($query, $attribute, array $config, $slug)
    {
        $separator = $config['separator'];

        return $query->where($attribute, $slug)
                     ->orWhere($attribute, 'LIKE', $slug.$separator.'%');
    }

    public function findSlug($slug, $columns = ['*'])
    {
        return $this->whereSlug($slug)->first($columns);
    }

    public function permalinkable()
    {
        $result = [];
        $permalinkable = isset($this->permalinkable) ? $this->permalinkable : [];
        foreach ($permalinkable as $attribute => $config) {
            if (is_numeric($attribute)) {
                $attribute = $config;
                $config = [];
            }

            $result[$attribute] = $config;
        }

        return $result;
    }

    /**
     * @return \Igniter\Flame\Database\PermalinkMaker
     */
    protected function getPermalinkMaker()
    {
        return PermalinkMaker::instance();
    }
}


<?php

namespace Neutrino\Database;

use Neutrino\Constants\Services;
use Neutrino\Support\DesignPatterns\Strategy;
use Phalcon\Db\AdapterInterface;
use Phalcon\Db\ColumnInterface;
use Phalcon\Db\DialectInterface;
use Phalcon\Db\IndexInterface;
use Phalcon\Db\RawValue;
use Phalcon\Db\ReferenceInterface;
use Phalcon\Db\ResultInterface;
use Phalcon\Di;

class DatabaseStrategy implements Strategy\StrategyInterface, AdapterInterface
{
    use Strategy\StrategyTrait;

    protected $_di;

    /**
     * CacheStrategy constructor.
     */
    public function __construct()
    {
        $database = $this->di(Services::CONFIG)->database;

        $this->default = $database->default;

        $this->supported = array_keys((array)$database->connections);
    }

    /**
     * @inheritdoc
     */
    protected function make($use)
    {
        return $this->di(Services::DB . '.' . $use);
    }

    protected function di($service)
    {
        if (isset($this->$service)) {
            return $this->$service;
        }

        if (!isset($this->_di)) {
            $this->_di = Di::getDefault();
        }

        return $this->$service = $this->_di->getShared($service);
    }

    public function __call($name, $arguments)
    {
        return $this->uses()->$name(...$arguments);
    }

    /**
     * This method is automatically called in \Phalcon\Db\Adapter\Pdo constructor.
     * Call it when you need to restore a database connection
     *
     * @param array $descriptor
     * @param array $args
     * @return bool
     */
    public function connect(array $descriptor = null, ...$args)
    {
        return $this->uses()->connect($descriptor, ...$args);
    }

    /**
     * Sends SQL statements to the database server returning the success state.
     * Use this method only when the SQL statement sent to the server return rows
     *
     * @param string $sqlStatement
     * @param mixed $placeholders
     * @param mixed $dataTypes
     * @param array $args
     * @return bool|ResultInterface
     */
    public function query($sqlStatement, $placeholders = null, $dataTypes = null, ...$args)
    {
        return $this->uses()->query($sqlStatement, $placeholders, $dataTypes, ...$args);
    }

    /**
     * Sends SQL statements to the database server returning the success state.
     * Use this method only when the SQL statement sent to the server doesn't return any rows
     *
     * @param string $sqlStatement
     * @param mixed $placeholders
     * @param mixed $dataTypes
     * @param array $args
     * @return bool
     */
    public function execute($sqlStatement, $placeholders = null, $dataTypes = null, ...$args)
    {
        return $this->uses()->execute($sqlStatement, $placeholders, $dataTypes, ...$args);
    }

    /**
     * Returns the number of affected rows by the last INSERT/UPDATE/DELETE reported by the database system
     *
     * @param array $args
     * @return int
     */
    public function affectedRows(...$args)
    {
        return $this->uses()->affectedRows(...$args);
    }

    /**
     * Closes active connection returning success. Phalcon automatically closes
     * and destroys active connections within Phalcon\Db\Pool
     *
     * @param array $args
     * @return bool
     */
    public function close(...$args)
    {
        return $this->uses()->close(...$args);
    }

    /**
     * Escapes a value to avoid SQL injections
     *
     * @param string $str
     * @param array $args
     * @return string
     */
    public function escapeString($str, ...$args)
    {
        return $this->uses()->escapeString($str, ...$args);
    }

    /**
     * Returns insert id for the auto_increment column inserted in the last SQL statement
     *
     * @param string $sequenceName
     * @param array $args
     * @return int
     */
    public function lastInsertId($sequenceName = null, ...$args)
    {
        return $this->uses()->lastInsertId($sequenceName, ...$args);
    }

    /**
     * Starts a transaction in the connection
     *
     * @param bool $nesting
     * @param array $args
     * @return bool
     */
    public function begin($nesting = true, ...$args)
    {
        return $this->uses()->begin($nesting, ...$args);
    }

    /**
     * Rollbacks the active transaction in the connection
     *
     * @param bool $nesting
     * @param array $args
     * @return bool
     */
    public function rollback($nesting = true, ...$args)
    {
        return $this->uses()->rollback($nesting, ...$args);
    }

    /**
     * Commits the active transaction in the connection
     *
     * @param bool $nesting
     * @param array $args
     * @return bool
     */
    public function commit($nesting = true, ...$args)
    {
        return $this->uses()->commit($nesting, ...$args);
    }

    /**
     * Checks whether connection is under database transaction
     *
     * @param array $args
     * @return bool
     */
    public function isUnderTransaction(...$args)
    {
        return $this->uses()->isUnderTransaction(...$args);
    }

    /**
     * Return internal PDO handler
     *
     * @param array $args
     * @return \Pdo
     */
    public function getInternalHandler(...$args)
    {
        return $this->uses()->getInternalHandler(...$args);
    }

    /**
     * Returns an array of Phalcon\Db\Column objects describing a table
     *
     * @param string $table
     * @param string $schema
     * @param array $args
     * @return ColumnInterface[]
     */
    public function describeColumns($table, $schema = null, ...$args)
    {
        return $this->uses()->describeColumns($table, $schema, ...$args);
    }

    /**
     * Returns the first row in a SQL query result
     *
     * @param string $sqlQuery
     * @param int $fetchMode
     * @param int $placeholders
     * @param array $args
     * @return array
     */
    public function fetchOne($sqlQuery, $fetchMode = 2, $placeholders = null, ...$args)
    {
        return $this->uses()->fetchOne($sqlQuery, $fetchMode, $placeholders, ...$args);
    }

    /**
     * Dumps the complete result of a query into an array
     *
     * @param string $sqlQuery
     * @param int $fetchMode
     * @param int $placeholders
     * @param array $args
     * @return array
     */
    public function fetchAll($sqlQuery, $fetchMode = 2, $placeholders = null, ...$args)
    {
        return $this->uses()->fetchAll($sqlQuery, $fetchMode, $placeholders, ...$args);
    }

    /**
     * Inserts data into a table using custom RDBMS SQL syntax
     *
     * @param mixed $table
     * @param array $values
     * @param mixed $fields
     * @param mixed $dataTypes
     * @param array $args
     * @return mixed
     */
    public function insert($table, array $values, $fields = null, $dataTypes = null, ...$args)
    {
        return $this->uses()->insert($table, $values, $fields, $dataTypes, ...$args); }

    /**
     * Updates data on a table using custom RDBMS SQL syntax
     *
     * @param mixed $table
     * @param mixed $fields
     * @param mixed $values
     * @param mixed $whereCondition
     * @param mixed $dataTypes
     * @param array $args
     * @return mixed
     */
    public function update($table, $fields, $values, $whereCondition = null, $dataTypes = null, ...$args)
    {
        return $this->uses()->update($table, $fields, $values, $whereCondition, $dataTypes, ...$args);
    }

    /**
     * Deletes data from a table using custom RDBMS SQL syntax
     *
     * @param string $table
     * @param string $whereCondition
     * @param array $placeholders
     * @param array $dataTypes
     * @param array $args
     * @return boolean
     */
    public function delete($table, $whereCondition = null, $placeholders = null, $dataTypes = null, ...$args)
    {
        return $this->uses()->delete($table, $whereCondition, $placeholders, $dataTypes, ...$args);
    }

    /**
     * Gets a list of columns
     *
     * @param mixed $columnList
     * @param array $args
     * @return    string
     */
    public function getColumnList($columnList, ...$args)
    {
        return $this->uses()->getColumnList($columnList, ...$args);
    }

    /**
     * Appends a LIMIT clause to sqlQuery argument
     *
     * @param mixed $sqlQuery
     * @param mixed $number
     * @param array $args
     * @return mixed
     */
    public function limit($sqlQuery, $number, ...$args)
    {
        return $this->uses()->limit($sqlQuery, $number, ...$args);
    }

    /**
     * Generates SQL checking for the existence of a schema.table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param array $args
     * @return bool
     */
    public function tableExists($tableName, $schemaName = null, ...$args)
    {
        return $this->uses()->tableExists($tableName, $schemaName, ...$args);
    }

    /**
     * Generates SQL checking for the existence of a schema.view
     *
     * @param string $viewName
     * @param string $schemaName
     * @param array $args
     * @return bool
     */
    public function viewExists($viewName, $schemaName = null, ...$args)
    {
        return $this->uses()->viewExists($viewName, $schemaName, ...$args);
    }

    /**
     * Returns a SQL modified with a FOR UPDATE clause
     *
     * @param string $sqlQuery
     * @param array $args
     * @return string
     */
    public function forUpdate($sqlQuery, ...$args)
    {
        return $this->uses()->forUpdate($sqlQuery, ...$args);
    }

    /**
     * Returns a SQL modified with a LOCK IN SHARE MODE clause
     *
     * @param string $sqlQuery
     * @param array $args
     * @return string
     */
    public function sharedLock($sqlQuery, ...$args)
    {
        return $this->uses()->sharedLock($sqlQuery, ...$args);
    }

    /**
     * Creates a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param array $definition
     * @param array $args
     * @return bool
     */
    public function createTable($tableName, $schemaName, array $definition, ...$args)
    {
        return $this->uses()->createTable($tableName, $schemaName, $definition, ...$args); }

    /**
     * Drops a table from a schema/database
     *
     * @param string $tableName
     * @param string $schemaName
     * @param bool $ifExists
     * @param array $args
     * @return bool
     */
    public function dropTable($tableName, $schemaName = null, $ifExists = true, ...$args)
    {
        return $this->uses()->dropTable($tableName, $schemaName, $ifExists, ...$args);
    }

    /**
     * Creates a view
     *
     * @param string $viewName
     * @param array $definition
     * @param string $schemaName
     * @param array $args
     * @return bool
     */
    public function createView($viewName, array $definition, $schemaName = null, ...$args)
    {
        return $this->uses()->createView($viewName, $definition, $schemaName, ...$args); }

    /**
     * Drops a view
     *
     * @param string $viewName
     * @param string $schemaName
     * @param bool $ifExists
     * @param array $args
     * @return bool
     */
    public function dropView($viewName, $schemaName = null, $ifExists = true, ...$args)
    {
        return $this->uses()->dropView($viewName, $schemaName, $ifExists, ...$args);
    }

    /**
     * Adds a column to a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param ColumnInterface $column
     * @param array $args
     * @return bool
     */
    public function addColumn($tableName, $schemaName, ColumnInterface $column, ...$args)
    {
        return $this->uses()->addColumn($tableName, $schemaName, $column, ...$args); }

    /**
     * Modifies a table column based on a definition
     *
     * @param string $tableName
     * @param string $schemaName
     * @param ColumnInterface $column
     * @param ColumnInterface $currentColumn
     * @param array $args
     * @return bool
     */
    public function modifyColumn($tableName, $schemaName, ColumnInterface $column, ColumnInterface $currentColumn = null, ...$args)
    {
        return $this->uses()->modifyColumn($tableName, $schemaName, $column, $currentColumn, ...$args); }

    /**
     * Drops a column from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $columnName
     * @param array $args
     * @return bool
     */
    public function dropColumn($tableName, $schemaName, $columnName, ...$args)
    {
        return $this->uses()->dropColumn($tableName, $schemaName, $columnName, ...$args);
    }

    /**
     * Adds an index to a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param IndexInterface $index
     * @param array $args
     * @return bool
     */
    public function addIndex($tableName, $schemaName, IndexInterface $index, ...$args)
    {
        return $this->uses()->addIndex($tableName, $schemaName, $index, ...$args); }

    /**
     * Drop an index from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $indexName
     * @param array $args
     * @return bool
     */
    public function dropIndex($tableName, $schemaName, $indexName, ...$args)
    {
        return $this->uses()->dropIndex($tableName, $schemaName, $indexName, ...$args);
    }

    /**
     * Adds a primary key to a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param IndexInterface $index
     * @param array $args
     * @return bool
     */
    public function addPrimaryKey($tableName, $schemaName, IndexInterface $index, ...$args)
    {
        return $this->uses()->addPrimaryKey($tableName, $schemaName, $index, ...$args); }

    /**
     * Drops primary key from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param array $args
     * @return bool
     */
    public function dropPrimaryKey($tableName, $schemaName, ...$args)
    {
        return $this->uses()->dropPrimaryKey($tableName, $schemaName, ...$args);
    }

    /**
     * Adds a foreign key to a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param ReferenceInterface $reference
     * @param array $args
     * @return bool
     */
    public function addForeignKey($tableName, $schemaName, ReferenceInterface $reference, ...$args)
    {
        return $this->uses()->addForeignKey($tableName, $schemaName, $reference, ...$args); }

    /**
     * Drops a foreign key from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $referenceName
     * @param array $args
     * @return bool
     */
    public function dropForeignKey($tableName, $schemaName, $referenceName, ...$args)
    {
        return $this->uses()->dropForeignKey($tableName, $schemaName, $referenceName, ...$args);
    }

    /**
     * Returns the SQL column definition from a column
     *
     * @param ColumnInterface $column
     * @param array $args
     * @return string
     */
    public function getColumnDefinition(ColumnInterface $column, ...$args)
    {
        return $this->uses()->getColumnDefinition($column, ...$args); }

    /**
     * List all tables on a database
     *
     * @param string $schemaName
     * @param array $args
     * @return array
     */
    public function listTables($schemaName = null, ...$args)
    {
        return $this->uses()->listTables($schemaName, ...$args);
    }

    /**
     * List all views on a database
     *
     * @param string $schemaName
     * @param array $args
     * @return array
     */
    public function listViews($schemaName = null, ...$args)
    {
        return $this->uses()->listViews($schemaName, ...$args);
    }

    /**
     * Return descriptor used to connect to the active database
     *
     * @param array $args
     * @return array
     */
    public function getDescriptor(...$args)
    {
        return $this->uses()->getDescriptor(...$args);
    }

    /**
     * Gets the active connection unique identifier
     *
     * @param array $args
     * @return string
     */
    public function getConnectionId(...$args)
    {
        return $this->uses()->getConnectionId(...$args);
    }

    /**
     * Active SQL statement in the object
     *
     * @param array $args
     * @return string
     */
    public function getSQLStatement(...$args)
    {
        return $this->uses()->getSQLStatement(...$args);
    }

    /**
     * Active SQL statement in the object without replace bound parameters
     *
     * @param array $args
     * @return string
     */
    public function getRealSQLStatement(...$args)
    {
        return $this->uses()->getRealSQLStatement(...$args);
    }

    /**
     * Active SQL statement in the object
     *
     * @param array $args
     * @return array
     */
    public function getSQLVariables(...$args)
    {
        return $this->uses()->getSQLVariables(...$args);
    }

    /**
     * Active SQL statement in the object
     *
     * @param array $args
     * @return array
     */
    public function getSQLBindTypes(...$args)
    {
        return $this->uses()->getSQLBindTypes(...$args);
    }

    /**
     * Returns type of database system the adapter is used for
     *
     * @param array $args
     * @return string
     */
    public function getType(...$args)
    {
        return $this->uses()->getType(...$args);
    }

    /**
     * Returns the name of the dialect used
     *
     * @param array $args
     * @return string
     */
    public function getDialectType(...$args)
    {
        return $this->uses()->getDialectType(...$args);
    }

    /**
     * Returns internal dialect instance
     *
     * @param array $args
     * @return DialectInterface
     */
    public function getDialect(...$args)
    {
        return $this->uses()->getDialect(...$args);
    }

    /**
     * Escapes a column/table/schema name
     *
     * @param string $identifier
     * @param array $args
     * @return string
     */
    public function escapeIdentifier($identifier, ...$args)
    {
        return $this->uses()->escapeIdentifier($identifier, ...$args);
    }

    /**
     * Lists table indexes
     *
     * @param string $table
     * @param string $schema
     * @param array $args
     * @return IndexInterface[]
     */
    public function describeIndexes($table, $schema = null, ...$args)
    {
        return $this->uses()->describeIndexes($table, $schema, ...$args);
    }

    /**
     * Lists table references
     *
     * @param string $table
     * @param string $schema
     * @param array $args
     * @return ReferenceInterface[]
     */
    public function describeReferences($table, $schema = null, ...$args)
    {
        return $this->uses()->describeReferences($table, $schema, ...$args);
    }

    /**
     * Gets creation options from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param array $args
     * @return array
     */
    public function tableOptions($tableName, $schemaName = null, ...$args)
    {
        return $this->uses()->tableOptions($tableName, $schemaName, ...$args);
    }

    /**
     * Check whether the database system requires an explicit value for identity columns
     *
     * @param array $args
     * @return bool
     */
    public function useExplicitIdValue(...$args)
    {
        return $this->uses()->useExplicitIdValue(...$args);
    }

    /**
     * Return the default identity value to insert in an identity column
     *
     * @param array $args
     * @return RawValue
     */
    public function getDefaultIdValue(...$args)
    {
        return $this->uses()->getDefaultIdValue(...$args);
    }

    /**
     * Check whether the database system requires a sequence to produce auto-numeric values
     *
     * @param array $args
     * @return bool
     */
    public function supportSequences(...$args)
    {
        return $this->uses()->supportSequences(...$args);
    }

    /**
     * Creates a new savepoint
     *
     * @param string $name
     * @param array $args
     * @return bool
     */
    public function createSavepoint($name, ...$args)
    {
        return $this->uses()->createSavepoint($name, ...$args);
    }

    /**
     * Releases given savepoint
     *
     * @param string $name
     * @param array $args
     * @return bool
     */
    public function releaseSavepoint($name, ...$args)
    {
        return $this->uses()->releaseSavepoint($name, ...$args);
    }

    /**
     * Rollbacks given savepoint
     *
     * @param string $name
     * @param array $args
     * @return bool
     */
    public function rollbackSavepoint($name, ...$args)
    {
        return $this->uses()->rollbackSavepoint($name, ...$args);
    }

    /**
     * Set if nested transactions should use savepoints
     *
     * @param bool $nestedTransactionsWithSavepoints
     * @param array $args
     * @return AdapterInterface
     */
    public function setNestedTransactionsWithSavepoints($nestedTransactionsWithSavepoints, ...$args)
    {
        return $this->uses()->setNestedTransactionsWithSavepoints($nestedTransactionsWithSavepoints, ...$args);
    }

    /**
     * Returns if nested transactions should use savepoints
     *
     * @param array $args
     * @return bool
     */
    public function isNestedTransactionsWithSavepoints(...$args)
    {
        return $this->uses()->isNestedTransactionsWithSavepoints(...$args);
    }

    /**
     * Returns the savepoint name to use for nested transactions
     *
     * @param array $args
     * @return string
     */
    public function getNestedTransactionSavepointName(...$args)
    {
        return $this->uses()->getNestedTransactionSavepointName(...$args);
    }
}


<?php

namespace Nextras\TracyQueryPanel;

use Latte;
use Tracy;

class QueryPanel implements Tracy\IBarPanel
{

	/** @var QueryCollector */
	protected $collector;

	/** @var array [float $min, float $max] */
	private $extremes;

	public function __construct()
	{
		$this->collector = new QueryCollector();
	}

	public function addQuery(IVoidQuery $query)
	{
		$this->collector->addQuery($query);
	}

	/**
	 * @return string
	 * @internal
	 */
	public function getTitle()
	{
		$c = $this->collector->count();
		if ($c === 0)
		{
			$title = 'no queries';
		}
		else if ($c === 1)
		{
			$title = '1 query';
		}
		else
		{
			$title = "$c queries";
		}

		return "$title, " . number_format($this->collector->getTotalElapsedTime(), 1) . ' ms';
	}

	/**
	 * Renders HTML code for custom tab.
	 *
	 * @return string
	 * @internal
	 */
	public function getTab()
	{
		$img = base64_encode(file_get_contents(__DIR__ . '/icon.svg'));
		return ''
			. $this->getTitle()
			. '';
	}

	/**
	 * Renders HTML code for custom panel.
	 *
	 * @return string html
	 * @internal
	 */
	public function getPanel()
	{
		$latte = new Latte\Engine;

		$latte->addFilter('storageId', [$this, 'getStorageId']);
		$latte->addFilter('colorRange', [$this, 'getColorInRange']);

		$args = [
			'title' => $this->getTitle(),
			'collector' => $this->collector,
		];

		if ($this->collector->getQueries())
		{
			$this->extremes = $this->collector->getTimeExtremes();
		}

		return $latte->renderToString(__DIR__ . '/queryPanel.latte', $args);
	}

	/**
	 * @internal
	 * @param IQuery|stdClass $query
	 * @return string
	 * @internal
	 */
	public function getStorageId($query)
	{
		if ($query instanceof IVoidQuery)
		{
			return $query->getStorageType() . '|' . $query->getDatabaseName();
		}
		// else is aggregation, stdClass
		return $query->storageType . '|' . $query->databaseName;
	}

	/**
	 * Linear color gradient
	 * @param float $value
	 * @return string hex color
	 * @internal
	 */
	public function getColorInRange($value)
	{
		$a = [54, 170, 31];
		$b = [220, 1, 57];

		list($min, $max) = $this->extremes;

		$d = $max - $min;
		$lin = ($value - $min) / ($d ?: 0.5); // prevent x/0

		$color = [];
		for ($i = 0; $i < 3; ++$i)
		{
			$color[$i] = (int) ($a[$i] + ($b[$i] - $a[$i]) * $lin);
		}

		return 'rgb(' . implode(',', $color) . ')';
	}

}


<?php

namespace Neutrino\Error\Writer;

use Neutrino\Cli\Output\Block;
use Neutrino\Constants\Services;
use Neutrino\Error\Error;
use Neutrino\Error\Helper;
use Phalcon\Di;
use Phalcon\Logger as PhalconLogger;

/**
 * Class Cli
 *
 * @package     Neutrino\Error\Writer
 */
class Cli implements Writable
{
    /**
     * @inheritdoc
     */
    public function handle(Error $error)
    {
        $di = Di::getDefault();

        if ($di && $di->has(Services\Cli::OUTPUT)) {
            /** @var \Neutrino\Cli\Output\Writer $output */
            $output = $di->getShared(Services\Cli::OUTPUT);

            $output->line('');

            $block = new Block($output, $this->getColoration($error), ['padding' => 4]);

            $block->draw(explode("\n", Helper::format($error)));
        } else {
            echo Helper::format($error);
        }
    }

    /**
     * @param \Neutrino\Error\Error $error
     *
     * @return string
     */
    protected function getColoration(Error $error)
    {
        if($error->isException){
            return 'error';
        }

        switch (Helper::getLogType($error->code)){
            case PhalconLogger::ALERT:
            case PhalconLogger::CRITICAL:
            case PhalconLogger::EMERGENCY:
            case PhalconLogger::ERROR:
                return 'error';
            case PhalconLogger::WARNING:
                return 'warn';
            case PhalconLogger::NOTICE:
                return 'notice';
            case PhalconLogger::INFO:
                return 'info';
            default:
                return 'error';
        }
    }
}


<?php

namespace Neutrino\Repositories;

use Neutrino\Interfaces\Repositories\RepositoryInterface;
use Neutrino\Repositories\Exceptions\TransactionException;
use Neutrino\Support\Arr;
use Phalcon\Di\Injectable;
use Phalcon\Mvc\Model\Transaction;

/**
 * Class Repository
 *
 * @package Neutrino\Repositories
 */
abstract class Repository extends Injectable implements RepositoryInterface
{
    /** @var \Neutrino\Model */
    protected $modelClass;

    /** @var \Phalcon\Mvc\Model\MessageInterface[] */
    protected $messages = [];

    /**
     * Repository constructor.
     *
     * @param null $modelClass
     *
     * @throws \RuntimeException
     */
    public function __construct($modelClass = null)
    {
        $this->modelClass = is_null($modelClass) ? $this->modelClass : $modelClass;

        if (empty($this->modelClass)) {
            throw new \RuntimeException(static::class . ' must have a $modelClass.');
        }
    }

    /**
     * @inheritdoc
     */
    public function all()
    {
        $class = $this->modelClass;

        return $class::find();
    }

    /**
     * @inheritdoc
     */
    public function count(array $params = null)
    {
        $class = $this->modelClass;

        return $class::count($this->paramsToCriteria($params));
    }

    /**
     * @inheritdoc
     */
    public function find(array $params = [], array $order = null, $limit = null, $offset = null)
    {
        $class = $this->modelClass;

        return $class::find($this->paramsToCriteria($params, $order, $limit, $offset));
    }

    /**
     * @inheritdoc
     */
    public function first(array $params = [], array $order = null)
    {
        $class = $this->modelClass;

        return $class::findFirst($this->paramsToCriteria($params, $order));
    }

    public function average($column, array $params = [], array $order = null, $limit = null, $offset = null)
    {
        $class = $this->modelClass;

        $parameters = $this->paramsToCriteria($params, $order, $limit, $offset);

        $parameters['column'] = $column;

        return $class::average($parameters);
    }

    public function minimum($column, array $params = [], array $order = null, $limit = null, $offset = null)
    {
        $class = $this->modelClass;

        $parameters = $this->paramsToCriteria($params, $order, $limit, $offset);

        $parameters['column'] = $column;

        return $class::minimum($parameters);
    }

    public function maximum($column, array $params = [], array $order = null, $limit = null, $offset = null)
    {
        $class = $this->modelClass;

        $parameters = $this->paramsToCriteria($params, $order, $limit, $offset);

        $parameters['column'] = $column;

        return $class::maximum($parameters);
    }

    /**
     * @param array $params
     * @param bool  $create
     * @param bool  $withTransaction
     *
     * @return \Neutrino\Model|\Phalcon\Mvc\Model
     * @throws \Neutrino\Repositories\Exceptions\TransactionException
     */
    public function firstOrNew(array $params = [], $create = false, $withTransaction = false)
    {
        $model = $this->first($params);

        if ($model === false) {
            $class = $this->modelClass;

            $model = new $class;

            foreach ($params as $key => $param) {
                $model->$key = $param;
            }

            if ($create && $this->create($model, $withTransaction) === false) {
                throw new TransactionException(__METHOD__ . ': can\'t create model : ' . get_class($model));
            };
        }

        return $model;
    }

    /**
     * @param array $params
     * @param bool  $withTransaction
     *
     * @return \Neutrino\Model|\Phalcon\Mvc\Model
     */
    public function firstOrCreate(array $params = [], $withTransaction = false)
    {
        return $this->firstOrNew($params, true, $withTransaction);
    }

    /**
     * @inheritdoc
     */
    public function each(array $params = [], $start = null, $end = null, $pad = 100, array $order = null)
    {
        if (is_null($start)) {
            $start = 0;
        }

        if (is_null($end)) {
            $end = INF;
        }

        if ($start >= $end) {
            return;
        }

        $class = $this->modelClass;

        $nb   = ceil(($end - $start) / $pad);
        $idx  = 0;
        $page = 0;
        do {
            $finish = true;

            $models = $class::find($this->paramsToCriteria($params, $order, $pad, ($start + ($pad * $page))));

            foreach ($models as $model) {
                $finish = false;

                yield $idx => $model;

                $idx++;
            }

            $page++;

            if ($page >= $nb) {
                $finish = true;
            }
        } while (!$finish);
    }

    /**
     * @param \Neutrino\Model|\Neutrino\Model[] $value
     * @param bool                              $withTransaction
     *
     * @return bool
     */
    public function create($value, $withTransaction = true)
    {
        if ($withTransaction) {
            return $this->transactionCall(is_array($value) ? $value : [$value], __FUNCTION__);
        }

        return $this->basicCall(is_array($value) ? $value : [$value], __FUNCTION__);
    }

    /**
     * @param \Neutrino\Model|\Neutrino\Model[] $value
     * @param bool                              $withTransaction
     *
     * @return bool
     */
    public function save($value, $withTransaction = true)
    {
        if ($withTransaction) {
            return $this->transactionCall(is_array($value) ? $value : [$value], __FUNCTION__);
        }

        return $this->basicCall(is_array($value) ? $value : [$value], __FUNCTION__);
    }

    /**
     * @param \Neutrino\Model|\Neutrino\Model[] $value
     * @param bool                              $withTransaction
     *
     * @return bool
     */
    public function update($value, $withTransaction = true)
    {
        if ($withTransaction) {
            return $this->transactionCall(is_array($value) ? $value : [$value], __FUNCTION__);
        }

        return $this->basicCall(is_array($value) ? $value : [$value], __FUNCTION__);
    }

    /**
     * @param \Neutrino\Model|\Neutrino\Model[] $value
     * @param bool                              $withTransaction
     *
     * @return bool
     */
    public function delete($value, $withTransaction = true)
    {
        if ($withTransaction) {
            return $this->transactionCall(is_array($value) ? $value : [$value], __FUNCTION__);
        }

        return $this->basicCall(is_array($value) ? $value : [$value], __FUNCTION__);
    }

    /**
     * @return \Phalcon\Mvc\Model\MessageInterface[]
     */
    public function getMessages()
    {
        return $this->messages;
    }

    /**
     * @param array      $params
     * @param array|null $orders
     * @param null       $limit
     * @param null       $offset
     *
     * @return array
     */
    protected function paramsToCriteria(array $params = null, array $orders = null, $limit = null, $offset = null)
    {
        $criteria = [];

        if (!empty($params)) {
            $clauses = [];

            foreach ($params as $key => $value) {
                if (is_array($value)) {
                    if(isset($value['operator']) && array_key_exists('value', $value)){
                        if(is_array($value['value'])){
                            $clauses[] = "$key {$value['operator']} ({{$key}:array})";
                        } else {
                            $clauses[] = "$key {$value['operator']} :$key:";
                        }
                        $params[$key] = $value['value'];
                    } else {
                        $clauses[] = "$key IN ({{$key}:array})";
                    }
                } elseif (is_string($value)) {
                    $clauses[] = "$key LIKE :$key:";
                } else {
                    $clauses[] = "$key = :$key:";
                }
            }

            $criteria = [
                implode(' AND ', $clauses),
                'bind' => $params
            ];
        }

        if (!empty($orders)) {
            $_orders = [];
            foreach ($orders as $key => $order) {
                if (is_int($key)) {
                    $key   = $order;
                    $order = 'ASC';
                }
                $_orders[] = "$key $order";
            }

            $criteria['order'] = implode(', ', $_orders);
        }

        if (isset($limit)) {
            $criteria['limit'] = $limit;
        }

        if (isset($offset)) {
            $criteria['offset'] = $offset;
        }

        return $criteria;
    }

    /**
     * @param array $values
     * @param       $method
     *
     * @return bool
     */
    protected function basicCall(array $values, $method)
    {
        try {
            $this->messages = [];

            foreach ($values as $item) {
                if ($item->$method() === false) {
                    $this->messages = array_merge($this->messages, $item->getMessages());
                }
            }

            if (!empty($this->messages)) {
                throw new TransactionException(
                    get_class(Arr::fetch($values, 0)) . ':' . $method .
                    ': failed. Show ' . static::class . '::getMessages().'
                );
            }
        } catch (\Exception $e) {
            $this->messages[] = $e->getMessage();

            return false;
        }

        return true;
    }

    /**
     * @param \Neutrino\Model[]|\Phalcon\Mvc\Model[] $values
     * @param string                                 $method
     *
     * @return bool
     */
    protected function transactionCall(array $values, $method)
    {
        if (empty($values)) {
            return true;
        }

        /** @var \Phalcon\Mvc\Model\Transaction $tx */
        $tx = $this->getDI()->getShared(Transaction\Manager::class)->get();

        try {
            $this->messages = [];

            foreach ($values as $item) {

                $item->setTransaction($tx);

                if ($item->$method() === false) {
                    $this->messages = array_merge($this->messages, $item->getMessages());
                }
            }

            if (!empty($this->messages)) {
                throw new TransactionException(
                    get_class(Arr::fetch($values, 0)) . ':' . $method .
                    ': failed. Show ' . static::class . '::getMessages().'
                );
            }

            if ($tx->commit() === false) {
                throw new TransactionException('Commit failed.');
            }

            return true;
        } catch (\Exception $e) {
            $tx->rollback();

            $this->messages[] = $e->getMessage();
            if (!is_null($messages = $tx->getMessages())) {
                $this->messages = array_merge($this->messages, $messages);
            }

            return false;
        }
    }
}


<?php

namespace Neutrino\Database\Schema\Dialect;

use Phalcon\Db;

/**
 * trait WrapperTrait
 *
 * @package Neutrino\Database\Schema\Dialect
 */
trait WrapperTrait
{
    /** @var \Phalcon\Db\DialectInterface */
    protected $dialect;

    /**
     * WrapperTrait constructor.
     *
     * @param \Phalcon\Db\DialectInterface $dialect
     */
    public function __construct(Db\DialectInterface $dialect)
    {
        $this->dialect = $dialect;
    }

    /**
     * Generates the SQL for LIMIT clause
     *
     * @param string $sqlQuery
     * @param mixed  $number
     *
     * @return string
     */
    public function limit($sqlQuery, $number)
    {
        return $this->dialect->limit($sqlQuery, $number);
    }

    /**
     * Returns a SQL modified with a FOR UPDATE clause
     *
     * @param string $sqlQuery
     *
     * @return string
     */
    public function forUpdate($sqlQuery)
    {
        return $this->dialect->forUpdate($sqlQuery);
    }

    /**
     * Returns a SQL modified with a LOCK IN SHARE MODE clause
     *
     * @param string $sqlQuery
     *
     * @return string
     */
    public function sharedLock($sqlQuery)
    {
        return $this->dialect->sharedLock($sqlQuery);
    }

    /**
     * Builds a SELECT statement
     *
     * @param array $definition
     *
     * @return string
     */
    public function select(array $definition)
    {
        return $this->dialect->select($definition);
    }

    /**
     * Checks whether the platform supports savepoints
     *
     * @return bool
     */
    public function supportsSavepoints()
    {
        return $this->dialect->supportsSavepoints();
    }

    /**
     * Checks whether the platform supports releasing savepoints.
     *
     * @return bool
     */
    public function supportsReleaseSavepoints()
    {
        return $this->dialect->supportsReleaseSavepoints();
    }

    /**
     * Generate SQL to create a new savepoint
     *
     * @param string $name
     *
     * @return string
     */
    public function createSavepoint($name)
    {
        return $this->dialect->createSavepoint($name);
    }

    /**
     * Generate SQL to release a savepoint
     *
     * @param string $name
     *
     * @return string
     */
    public function releaseSavepoint($name)
    {
        return $this->dialect->releaseSavepoint($name);
    }

    /**
     * Generate SQL to rollback a savepoint
     *
     * @param string $name
     *
     * @return string
     */
    public function rollbackSavepoint($name)
    {
        return $this->dialect->rollbackSavepoint($name);
    }

    /**
     * Gets the column name in RDBMS
     *
     * @param \Phalcon\Db\ColumnInterface $column
     *
     * @return string
     */
    public function getColumnDefinition(Db\ColumnInterface $column)
    {
        return $this->dialect->getColumnDefinition($column);
    }

    /**
     * Generates SQL to add a column to a table
     *
     * @param string                      $tableName
     * @param string                      $schemaName
     * @param \Phalcon\Db\ColumnInterface $column
     *
     * @return string
     */
    public function addColumn($tableName, $schemaName, Db\ColumnInterface $column)
    {
        return $this->dialect->addColumn($tableName, $schemaName, $column);
    }

    /**
     * Generates SQL to modify a column in a table
     *
     * @param string                      $tableName
     * @param string                      $schemaName
     * @param \Phalcon\Db\ColumnInterface $column
     * @param \Phalcon\Db\ColumnInterface $currentColumn
     *
     * @return string
     */
    public function modifyColumn(
        $tableName,
        $schemaName,
        Db\ColumnInterface $column,
        Db\ColumnInterface $currentColumn = null
    )
    {
        return $this->dialect->modifyColumn($tableName, $schemaName, $column, $currentColumn);
    }

    /**
     * Generates SQL to delete a column from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $columnName
     *
     * @return string
     */
    public function dropColumn($tableName, $schemaName, $columnName)
    {
        return $this->dialect->dropColumn($tableName, $schemaName, $columnName);
    }

    /**
     * Generates SQL to add an index to a table
     *
     * @param string                     $tableName
     * @param string                     $schemaName
     * @param \Phalcon\Db\IndexInterface $index
     *
     * @return string
     */
    public function addIndex($tableName, $schemaName, Db\IndexInterface $index)
    {
        return $this->dialect->addIndex($tableName, $schemaName, $index);
    }

    /**
     * Generates SQL to delete an index from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $indexName
     *
     * @return string
     */
    public function dropIndex($tableName, $schemaName, $indexName)
    {
        return $this->dialect->dropIndex($tableName, $schemaName, $indexName);
    }

    /**
     * Generates SQL to add the primary key to a table
     *
     * @param string                     $tableName
     * @param string                     $schemaName
     * @param \Phalcon\Db\IndexInterface $index
     *
     * @return string
     */
    public function addPrimaryKey($tableName, $schemaName, Db\IndexInterface $index)
    {
        return $this->dialect->addPrimaryKey($tableName, $schemaName, $index);
    }

    /**
     * Generates SQL to delete primary key from a table
     *
     * @param string $tableName
     * @param string $schemaName
     *
     * @return string
     */
    public function dropPrimaryKey($tableName, $schemaName)
    {
        return $this->dialect->dropPrimaryKey($tableName, $schemaName);
    }

    /**
     * Generates SQL to add an index to a table
     *
     * @param string                         $tableName
     * @param string                         $schemaName
     * @param \Phalcon\Db\ReferenceInterface $reference
     *
     * @return string
     */
    public function addForeignKey($tableName, $schemaName, Db\ReferenceInterface $reference)
    {
        return $this->dialect->addForeignKey($tableName, $schemaName, $reference);
    }

    /**
     * Generates SQL to delete a foreign key from a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param string $referenceName
     *
     * @return string
     */
    public function dropForeignKey($tableName, $schemaName, $referenceName)
    {
        return $this->dialect->dropForeignKey($tableName, $schemaName, $referenceName);
    }

    /**
     * Generates SQL to create a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param array  $definition
     *
     * @return string
     */
    public function createTable($tableName, $schemaName, array $definition)
    {
        return $this->dialect->createTable($tableName, $schemaName, $definition);
    }

    /**
     * Generates SQL to create a view
     *
     * @param string $viewName
     * @param array  $definition
     * @param string $schemaName
     *
     * @return string
     */
    public function createView($viewName, array $definition, $schemaName = null)
    {
        return $this->dialect->createView($viewName, $definition, $schemaName);
    }

    /**
     * Generates SQL to drop a table
     *
     * @param string $tableName
     * @param string $schemaName
     * @param bool   $ifExists
     *
     * @return string
     */
    public function dropTable($tableName, $schemaName = null, $ifExists = null)
    {
        return $this->dialect->dropTable($tableName, $schemaName, $ifExists);
    }

    /**
     * Generates SQL to drop a view
     *
     * @param string $viewName
     * @param string $schemaName
     * @param bool   $ifExists
     *
     * @return string
     */
    public function dropView($viewName, $schemaName = null, $ifExists = true)
    {
        return $this->dialect->dropView($viewName, $schemaName, $ifExists);
    }

    /**
     * Generates SQL checking for the existence of a schema.table
     *
     * @param string $tableName
     * @param string $schemaName
     *
     * @return string
     */
    public function tableExists($tableName, $schemaName = null)
    {
        return $this->dialect->tableExists($tableName, $schemaName);
    }

    /**
     * Generates SQL checking for the existence of a schema.view
     *
     * @param string $viewName
     * @param string $schemaName
     *
     * @return string
     */
    public function viewExists($viewName, $schemaName = null)
    {
        return $this->dialect->viewExists($viewName, $schemaName);
    }

    /**
     * Generates SQL to describe a table
     *
     * @param string $table
     * @param string $schema
     *
     * @return string
     */
    public function describeColumns($table, $schema = null)
    {
        return $this->dialect->describeColumns($table, $schema);
    }

    /**
     * List all tables in database
     *
     * @param string $schemaName
     *
     * @return string
     */
    public function listTables($schemaName = null)
    {
        return $this->dialect->listTables($schemaName);
    }

    /**
     * Generates SQL to query indexes on a table
     *
     * @param string $table
     * @param string $schema
     *
     * @return string
     */
    public function describeIndexes($table, $schema = null)
    {
        return $this->dialect->describeIndexes($table, $schema);
    }

    /**
     * Generates SQL to query foreign keys on a table
     *
     * @param string $table
     * @param string $schema
     *
     * @return string
     */
    public function describeReferences($table, $schema = null)
    {
        return $this->dialect->describeReferences($table, $schema);
    }

    /**
     * Generates the SQL to describe the table creation options
     *
     * @param string $table
     * @param string $schema
     *
     * @return string
     */
    public function tableOptions($table, $schema = null)
    {
        return $this->dialect->tableOptions($table, $schema);
    }

    /**
     * @param string $name
     * @param array  $arguments
     *
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        if (method_exists($this->dialect, $name)) {
            return $this->dialect->$name(...$arguments);
        }

        throw new \BadMethodCallException(
            'Method "' . $name . '" doesn\'t exist in "' . get_class($this->dialect) . '"'
        );
    }
}


<?php

namespace Igniter\Flame\Foundation;

use Exception;
use Igniter\Flame\Foundation\Providers\LogServiceProvider;
use Igniter\Flame\Router\RoutingServiceProvider;
use Illuminate\Events\EventServiceProvider;
use Illuminate\Foundation\Application as BaseApplication;

/**
 * Igniter Application Class
 *
 * @package        System\Classes\BaseController.php
 */
class Application extends BaseApplication
{
    /**
     * The base path for extensions.
     *
     * @var string
     */
    protected $extensionsPath;

    /**
     * The base path for themes.
     *
     * @var string
     */
    protected $themesPath;

    /**
     * The base path for views.
     *
     * @var string
     */
    protected $viewPath;

    /**
     * The base path for assets.
     *
     * @var string
     */
    protected $assetsPath;

    /**
     * The request execution context (main, admin)
     *
     * @var string
     */
    protected $appContext;

    /**
     * Indicates if the application has a valid database
     * connection and "settings" table.
     *
     * @var string
     */
    protected $hasDatabase;

    /**
     * Get the path to the database directory.
     *
     * @param  string $path Optionally, a path to append to the database path
     * @return string
     */
    public function databasePath($path = '')
    {
        return ($this->databasePath ?: $this->basePath.'/app/system/database').($path ? DIRECTORY_SEPARATOR.$path : $path);
    }

    /**
     * Get the path to the public directory.
     *
     * @return string
     */
    public function publicPath()
    {
        return $this->basePath;
    }

    /**
     * Get the path to the language files.
     *
     * @return string
     */
    public function langPath()
    {
        return $this->path('language');
    }

    /**
     * Get the path to the extensions directory.
     *
     * @return string
     */
    public function extensionsPath()
    {
        return $this->extensionsPath ?: $this->basePath.'/extensions';
    }

    /**
     * Get the path to the themes directory.
     *
     * @return string
     */
    public function themesPath()
    {
        return $this->themesPath ?: $this->basePath.'/themes';
    }

    /**
     * Get the path to the themes directory.
     *
     * @return string
     */
    public function assetsPath()
    {
        return $this->assetsPath ?: $this->basePath.'/assets';
    }

    /**
     * Get the path to the app context views directory.
     *
     * @return string
     */
    public function viewPaths()
    {
        return $this->viewPath ?: $this->basePath.'/app/'.$this->appContext.'/views';
    }

    /**
     * Register all of the base service providers.
     *
     * @return void
     */
    protected function registerBaseServiceProviders()
    {
        $this->register(new EventServiceProvider($this));

        $this->register(new LogServiceProvider($this));

        $this->register(new RoutingServiceProvider($this));
    }

    /**
     * Bind all of the application paths in the container.
     *
     * @return void
     */
    protected function bindPathsInContainer()
    {
        parent::bindPathsInContainer();

        foreach (['extensions', 'themes', 'assets', 'temp'] as $path) {
            $this->instance('path.'.$path, $this->{$path.'Path'}());
        }
    }

    /**
     * Set the extensions path for the application.
     *
     * @param  string $path
     *
     * @return $this
     */
    public function useExtensionsPath($path)
    {
        $this->extensionsPath = $path;
        $this->instance('path.extensions', $path);

        return $this;
    }

    /**
     * Set the themes path for the application.
     *
     * @param  string $path
     *
     * @return $this
     */
    public function useThemesPath($path)
    {
        $this->themesPath = $path;
        $this->instance('path.themes', $path);

        return $this;
    }

    /**
     * Set the assets path for the application.
     *
     * @param  string $path
     *
     * @return $this
     */
    public function useAssetsPath($path)
    {
        $this->assetsPath = $path;
        $this->instance('path.assets', $path);

        return $this;
    }

    /**
     * Get the path to the storage temp directory.
     *
     * @return string
     */
    public function tempPath()
    {
        return $this->basePath.'/storage/temp';
    }

    /**
     * Determine if we are running in the admin area.
     *
     * @return bool
     */
    public function runningInAdmin()
    {
        return $this->appContext == 'admin';
    }

    /**
     * Register a "before" application filter.
     *
     * @param  \Closure|string $callback
     *
     * @return void
     */
    public function before($callback)
    {
        return $this['router']->before($callback);
    }

    /**
     * Register an "after" application filter.
     *
     * @param  \Closure|string $callback
     *
     * @return void
     */
    public function after($callback)
    {
        return $this['router']->after($callback);
    }

    /**
     * Gets the execution context
     *
     * @return string
     */
    public function appContext()
    {
        return $this->appContext;
    }

    /**
     * Sets the execution context
     *
     * @param  string $context
     *
     * @return void
     */
    public function setAppContext($context)
    {
        $this->appContext = $context;
    }

    /**
     * Returns true if a database connection is present.
     * @return boolean
     */
    public function hasDatabase()
    {
        try {
            $hasDatabase = is_null($this->hasDatabase)
                ? $this['db.connection']->getSchemaBuilder()->hasTable('settings')
                : $this->hasDatabase;
        }
        catch (Exception $ex) {
            $hasDatabase = FALSE;
        }

        return $this->hasDatabase = $hasDatabase;
    }

    /**
     * Register the core class aliases in the container.
     *
     * @return void
     */
    public function registerCoreContainerAliases()
    {
        $aliases = [
            'app' => [\Igniter\Flame\Foundation\Application::class, \Illuminate\Contracts\Container\Container::class, \Illuminate\Contracts\Foundation\Application::class, \Psr\Container\ContainerInterface::class],
//            'auth'                 => [\Illuminate\Auth\AuthManager::class, \Illuminate\Contracts\Auth\Factory::class],
//            'auth.driver'          => [\Illuminate\Contracts\Auth\Guard::class],
            'blade.compiler' => [\Illuminate\View\Compilers\BladeCompiler::class],
            'cache' => [\Illuminate\Cache\CacheManager::class, \Illuminate\Contracts\Cache\Factory::class],
            'cache.store' => [\Illuminate\Cache\Repository::class, \Illuminate\Contracts\Cache\Repository::class],
            'config' => [\Illuminate\Config\Repository::class, \Illuminate\Contracts\Config\Repository::class],
            'cookie' => [\Illuminate\Cookie\CookieJar::class, \Illuminate\Contracts\Cookie\Factory::class, \Illuminate\Contracts\Cookie\QueueingFactory::class],
            'encrypter' => [\Illuminate\Encryption\Encrypter::class, \Illuminate\Contracts\Encryption\Encrypter::class],
            'db' => [\Illuminate\Database\DatabaseManager::class],
            'db.connection' => [\Illuminate\Database\Connection::class, \Illuminate\Database\ConnectionInterface::class],
            'events' => [\Illuminate\Events\Dispatcher::class, \Illuminate\Contracts\Events\Dispatcher::class],
            'files' => [\Illuminate\Filesystem\Filesystem::class],
            'filesystem' => [\Illuminate\Filesystem\FilesystemManager::class, \Illuminate\Contracts\Filesystem\Factory::class],
            'filesystem.disk' => [\Illuminate\Contracts\Filesystem\Filesystem::class],
            'filesystem.cloud' => [\Illuminate\Contracts\Filesystem\Cloud::class],
            'hash' => [\Illuminate\Contracts\Hashing\Hasher::class],
            'translator' => [\Illuminate\Translation\Translator::class, \Illuminate\Contracts\Translation\Translator::class],
            'log' => [\Illuminate\Log\Writer::class, \Illuminate\Contracts\Logging\Log::class, \Psr\Log\LoggerInterface::class],
            'mailer' => [\Illuminate\Mail\Mailer::class, \Illuminate\Contracts\Mail\Mailer::class, \Illuminate\Contracts\Mail\MailQueue::class],
//            'auth.password'        => [\Illuminate\Auth\Passwords\PasswordBrokerManager::class, \Illuminate\Contracts\Auth\PasswordBrokerFactory::class],
//            'auth.password.broker' => [\Illuminate\Auth\Passwords\PasswordBroker::class, \Illuminate\Contracts\Auth\PasswordBroker::class],
            'queue' => [\Illuminate\Queue\QueueManager::class, \Illuminate\Contracts\Queue\Factory::class, \Illuminate\Contracts\Queue\Monitor::class],
            'queue.connection' => [\Illuminate\Contracts\Queue\Queue::class],
            'queue.failer' => [\Illuminate\Queue\Failed\FailedJobProviderInterface::class],
            'redirect' => [\Illuminate\Routing\Redirector::class],
            'redis' => [\Illuminate\Redis\RedisManager::class, \Illuminate\Contracts\Redis\Factory::class],
            'request' => [\Illuminate\Http\Request::class, \Symfony\Component\HttpFoundation\Request::class],
            'router' => [\Illuminate\Routing\Router::class, \Illuminate\Contracts\Routing\Registrar::class, \Illuminate\Contracts\Routing\BindingRegistrar::class],
            'session' => [\Illuminate\Session\SessionManager::class],
            'session.store' => [\Illuminate\Session\Store::class, \Illuminate\Contracts\Session\Session::class],
            'url' => [\Illuminate\Routing\UrlGenerator::class, \Illuminate\Contracts\Routing\UrlGenerator::class],
            'validator' => [\Illuminate\Validation\Factory::class, \Illuminate\Contracts\Validation\Factory::class],
            'view' => [\Illuminate\View\Factory::class, \Illuminate\Contracts\View\Factory::class],
        ];

        foreach ($aliases as $key => $aliases) {
            foreach ($aliases as $alias) {
                $this->alias($key, $alias);
            }
        }
    }

    //
    // Caching
    //

    /**
     * Get the path to the configuration cache file.
     *
     * @return string
     */
    public function getCachedConfigPath()
    {
        return $this['path.storage'].'/framework/config.php';
    }

    /**
     * Get the path to the routes cache file.
     *
     * @return string
     */
    public function getCachedRoutesPath()
    {
        return $this['path.storage'].'/framework/routes.php';
    }

    /**
     * Get the path to the cached services.json file.
     *
     * @return string
     */
    public function getCachedServicesPath()
    {
        return $this->storagePath().'/framework/services.php';
    }

    /**
     * Get the path to the cached packages.php file.
     *
     * @return string
     */
    public function getCachedPackagesPath()
    {
        return $this->storagePath().'/framework/packages.php';
    }

    /**
     * Get the path to the cached packages.php file.
     *
     * @return string
     */
    public function getCachedClassesPath()
    {
        return $this->storagePath().'/framework/classes.php';
    }
}


<?php

namespace Neutrino;

use Phalcon\Di\Service;
use Phalcon\DiInterface;
use Phalcon\Mvc\ModuleDefinitionInterface;
use Phalcon\Mvc\User\Module as PhalconModule;

/**
 * Class Module
 *
 * @package     Neutrino
 * @property-read \Phalcon\Application|\Phalcon\Mvc\Application|\Phalcon\Cli\Console $application
 * @property-read \Phalcon\Config|\stdClass|\ArrayAccess                             $config
 *
 */
class Module extends PhalconModule implements ModuleDefinitionInterface
{
    /**
     * Return the Provider List to load.
     *
     * @var array
     */
    protected $providers = [];

    /**
     * Registers an autoloader related to the module
     *
     * @param \Phalcon\DiInterface $dependencyInjector
     */
    public function registerAutoloaders(DiInterface $dependencyInjector = null)
    {
    }

    /**
     * This methods registers the services to be used by the application
     *
     * @param \Phalcon\DiInterface $di
     */
    public function registerServices(DiInterface $di)
    {
        foreach ($this->providers as $name => $provider) {
            if (is_string($name)) {
                $service = new Service($name, $provider, true);

                $di->setRaw($name, $service);
                $di->setRaw($provider, $service);

                continue;
            }

            /* @var \Neutrino\Interfaces\Providable $prv */
            $prv = new $provider();

            $prv->registering();
        }

        $this->initialise($di);
    }

    /**
     * Initialise the Modules
     *
     * @param \Phalcon\DiInterface $di
     */
    public function initialise(DiInterface $di)
    {
    }
}


<?php

namespace Neutrino\Support\DesignPatterns\Strategy;

trait StrategyTrait
{
    /**
     * Supported Adapters
     *
     * @var array
     */
    protected $supported;

    /**
     * Default Adapter
     *
     * @var string
     */
    protected $default;

    /**
     * All registered Adapters
     *
     * @var array
     */
    private $adapters = [];

    /**
     * Current Adapter
     *
     * @var mixed
     */
    private $adapter;

    /**
     * Return / Change current adapter.
     *
     * @param string|null $use
     *
     * @return mixed
     * @throws \RuntimeException
     */
    public function uses($use = null)
    {
        if (!empty($use)) {
            if (!in_array($use, $this->supported)) {
                throw new \RuntimeException(static::class . " : $use unsupported. ");
            }
            if (!isset($this->adapters[$use])) {
                $this->adapters[$use] = $this->make($use);
            }
            $this->adapter = $this->adapters[$use];
        }

        if (empty($this->adapter)) {
            $this->adapter = $this->adapters[$this->default] = $this->make($this->default);
        }

        return $this->adapter;
    }

    /**
     * Make the instance & return them
     *
     * @param string $use
     *
     * @return mixed
     */
    protected function make($use)
    {
        return new $use;
    }
}


<?php

namespace Igniter\Flame\Currency\Drivers;

use DateTime;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Collection;

class Database extends AbstractDriver
{
    /**
     * Database manager instance.
     *
     * @var DatabaseManager
     */
    protected $database;

    /**
     * Create a new driver instance.
     *
     * @param array $config
     */
    public function __construct(array $config)
    {
        parent::__construct($config);

        $this->database = app('db')->connection($this->config('connection'));
    }

    /**
     * {@inheritdoc}
     */
    public function create(array $params)
    {
        // Ensure the currency doesn't already exist
        if ($this->find($params['code'], null) !== null) {
            return 'exists';
        }

        // Created at stamp
        $created = new DateTime('now');

        $params = array_merge([
            'currency_name'   => '',
            'currency_code'   => '',
            'currency_symbol' => '',
            'format'          => '',
            'currency_rate'   => 1,
            'currency_status' => 0,
//            'created_at' => $created,
            'date_modified'   => $created,
        ], $params);

        return $this->database->table($this->config('table'))->insert($params);
    }

    /**
     * {@inheritdoc}
     */
    public function all()
    {
        $collection = new Collection($this->database->table($this->config('table'))->get());

        return $collection->keyBy('currency_code')
                          ->map(function ($item) {

                              $format = $item->thousand_sign.'0'.$item->decimal_sign.str_repeat('0', $item->decimal_position);

                              return [
                                  'currency_id'     => $item->currency_id,
                                  'currency_name'   => $item->currency_name,
                                  'currency_code'   => strtoupper($item->currency_code),
                                  'currency_symbol' => $item->currency_symbol,
                                  'format'          => $item->symbol_position
                                      ? '1'.$format.$item->currency_symbol
                                      : $item->currency_symbol.'1'.$format,
                                  'currency_rate'   => $item->currency_rate,
                                  'currency_status' => $item->currency_status,
                                  'date_modified'   => $item->date_modified,
//                    'date_modified' => $item->date_modified,
                              ];
                          })
                          ->all();
    }

    /**
     * {@inheritdoc}
     */
    public function find($code, $active = 1)
    {
        $query = $this->database->table($this->config('table'))
                                ->where('currency_code', strtoupper($code));

        // Make active optional
        if (is_null($active) === FALSE) {
            $query->where('currency_status', $active);
        }

        return $query->first();
    }

    /**
     * {@inheritdoc}
     */
    public function update($code, array $attributes, DateTime $timestamp = null)
    {
        $table = $this->config('table');

        // Create timestamp
        if (empty($attributes['date_modified']) === TRUE) {
            $attributes['date_modified'] = new DateTime('now');
        }

        return $this->database->table($table)
                              ->where('currency_code', strtoupper($code))
                              ->update($attributes);
    }

    /**
     * {@inheritdoc}
     */
    public function delete($code)
    {
        $table = $this->config('table');

        return $this->database->table($table)
                              ->where('currency_code', strtoupper($code))
                              ->delete();
    }
}