<?php

namespace Neutrino\Database\Cli\Tasks;

/**
 * Class MigrationMakeTask
 *
 * @package Neutrino\Database\Cli\Tasks
 */
class MakerTask extends BaseTask
{
    /**
     * @description Create a new migration file.
     *
     * @argument    name : The name of the migration.
     *
     * @option      --create= : The table to be created.
     * @option      --table= : The table to be migrate.
     * @option      --path= : The location where the migration file should be created.
     */
    public function mainAction()
    {
        // It's possible for the developer to specify the tables to modify in this
        // schema operation. The developer may also specify if this table needs
        // to be freshly created so we can create the appropriate migrations.
        $name = trim($this->getArg('name'));
        $table = $this->getOption('table');
        $create = $this->getOption('create', false);

        // If no table was given as an option but a create option is given then we
        // will use the "create" option as the table name. This allows the devs
        // to pass a table name into this option as a short-cut for creating.
        if (!$table && is_string($create)) {
            $table = $create;

            $create = true;
        }

        // Next, we will attempt to guess the table name if this the migration has
        // "create" in the name. This will allow us to provide a convenient way
        // of creating migrations that create new tables for the application.
        if (!$table) {
            if (preg_match('/^create_(\w+)_table$/', $name, $matches)) {
                $table = $matches[1];

                $create = true;
            }
        }

        // Now we are ready to write the migration out to disk. Once we've written
        // the migration out, we will dump-autoload for the entire framework to
        // make sure that the migrations are registered by the class loaders.
        $this->writeMigration($name, $table, $create);
    }

    /**
     * Write the migration file to disk.
     *
     * @param  string $name
     * @param  string $table
     * @param  bool   $create
     */
    protected function writeMigration($name, $table, $create)
    {
        $file = pathinfo($this->creator->create(
            $name, $this->getMigrationPath(), $table, $create
        ), PATHINFO_FILENAME);

        $this->info("Created Migration: {$file}");
    }
}


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

use Igniter\Flame\Filesystem\Filesystem;
use Igniter\Flame\Support\ClassLoader;
use Illuminate\Contracts\Foundation\Application;

class RegisterClassLoader
{
    /**
     * Register Auto Loader
     *
     * @param  \Illuminate\Contracts\Foundation\Application $app
     *
     * @return void
     */
    public function bootstrap(Application $app)
    {
        $loader = new ClassLoader(
            new Filesystem,
            $app->basePath(),
            $app->getCachedClassesPath()
        );

        $app->instance(ClassLoader::class, $loader);

        $loader->register();

        $loader->addDirectories([
            'app',
            'extensions',
        ]);

        $app->after(function () use ($loader) {
            $loader->store();
        });
    }
}


<?php namespace Igniter\Flame\ActivityLog\Traits;

use App;
use Igniter\Flame\ActivityLog\ActivityLogger;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

/**
 * LogsActivity model trait
 *
 **
 * In the model class definition:
 *
 *   use \Igniter\Flame\Database\Traits\LogsActivity;
 *
 * You can log the changed attributes for all these events :
 *   protected static $logAttributes = ['name', 'text'];
 *
 * You can customize the events being logged :
 *   protected static $recordEvents = ['deleted'];
 *
 * You can customize the description :
 *   public function getMessageForEvent(string $eventName) {
 *      return "This model has been {$eventName}";
 *   };
 *
 * You can ignore changes to certain attributes :
 *   protected static $ignoreChangedAttributes = ['text'];
 *
 * You can log only the changed attributes :
 *   protected static $logOnlyDirty = true;
 *
 */
trait LogsActivity
{
    protected $enableLoggingModelsEvents = TRUE;

    protected $oldAttributes = [];

    protected static function bootLogsActivity()
    {
        static::eventsToBeRecorded()->each(function ($eventName) {
            return static::$eventName(function (Model $model) use ($eventName) {

                if ($eventName == 'updated') {
                    //temporary hold the original attributes on the model
                    //as we'll need these in the updating event
                    $oldValues = $model->replicate()->setRawAttributes($model->getOriginal());
                    $model->oldAttributes = static::logChanges($oldValues);
                }

                if (!$model->shouldLogEvent($eventName)) {
                    return;
                }

                $description = $model->getMessageForEvent($eventName);
                if ($description == '') {
                    return;
                }

                $model->getActivityLogger()
                      ->useLog($model->getLogNameToUse($eventName))
                      ->performedOn($model)
                      ->withProperties($model->attributeValuesToBeLogged($eventName))
                      ->log($description);
            });
        });
    }

    public function disableLogging()
    {
        $this->enableLoggingModelsEvents = FALSE;

        return $this;
    }

    public function enableLogging()
    {
        $this->enableLoggingModelsEvents = TRUE;

        return $this;
    }

    public function activity()
    {
        return $this->morphMany('System\Models\Activities_model', 'subject');
    }

    public function getMessageForEvent($eventName)
    {
        return $eventName;
    }

    public function getLogNameToUse($eventName = '')
    {
        return 'default';
    }

    /**
     * Get the event names that should be recorded.
     */
    protected static function eventsToBeRecorded()
    {
        if (isset(static::$recordEvents)) {
            return collect(static::$recordEvents);
        }

        $events = collect([
            'created',
            'updated',
            'deleted',
        ]);

        if (collect(class_uses(__CLASS__))->contains(SoftDeletes::class)) {
            $events->push('restored');
        }

        return $events;
    }

    public function attributesToBeIgnored()
    {
        if (!isset(static::$ignoreChangedAttributes)) {
            return [];
        }

        return static::$ignoreChangedAttributes;
    }

    /**
     * @return ActivityLogger
     */
    public function getActivityLogger()
    {
        return App::make(ActivityLogger::class);
    }

    public function shouldLogOnlyDirty()
    {
        if (!isset(static::$logOnlyDirty)) {
            return FALSE;
        }

        return static::$logOnlyDirty;
    }

    public function attributesToBeLogged()
    {
        if (!isset(static::$logAttributes)) {
            return [];
        }

        return static::$logAttributes;
    }

    protected function shouldLogEvent($eventName)
    {
        if (!$this->enableLoggingModelsEvents) {
            return FALSE;
        }

        if (!in_array($eventName, ['created', 'updated'])) {
            return TRUE;
        }

        if (array_has($this->getDirty(), 'date_deleted')) {
            if ($this->getDirty()['date_deleted'] === null) {
                return FALSE;
            }
        }

        //do not log update event if only ignored attributes are changed
        return (bool)count($this->getDirty());
    }

    public function attributeValuesToBeLogged($processingEvent)
    {
        if (!count($this->attributesToBeLogged())) {
            return [];
        }
        $properties['attributes'] = static::logChanges($this->exists ? $this->fresh() : $this);
        if (static::eventsToBeRecorded()->contains('updated') && $processingEvent == 'updated') {
            $nullProperties = array_fill_keys(array_keys($properties['attributes']), null);
            $properties['old'] = array_merge($nullProperties, $this->oldAttributes);
        }
        if ($this->shouldLogOnlyDirty() && isset($properties['old'])) {
            $properties['attributes'] = array_udiff(
                $properties['attributes'],
                $properties['old'],
                function ($new, $old) {
                    return strcmp($new, $old);
                }
            );
            $properties['old'] = collect($properties['old'])->only(array_keys($properties['attributes']))->all();
        }

        return $properties;
    }

    public static function logChanges(Model $model)
    {
        $changes = [];
        foreach ($model->attributesToBeLogged() as $attribute) {
            if (str_contains($attribute, '.')) {
                $changes += self::getRelatedModelAttributeValue($model, $attribute);
            }
            else {
                $changes += collect($model)->only($attribute)->toArray();
            }
        }

        return $changes;
    }

    protected static function getRelatedModelAttributeValue(Model $model, $attribute)
    {
        if (substr_count($attribute, '.') > 1) {
            throw new \Exception("Invalid attribute passed to {$attribute}");
        }

        list($relatedModelName, $relatedAttribute) = explode('.', $attribute);
        $relatedModel = isset($model->$relatedModelName) ? $model->$relatedModelName : $model->$relatedModelName();

        return ["{$relatedModelName}.{$relatedAttribute}" => $relatedModel->$relatedAttribute];
    }
}


<?php

namespace Neutrino\Debug;

use Neutrino\Constants\Services;
use Phalcon\Di;

/**
 * Class VarDump
 *
 * @package Neutrino\Debug
 */
class VarDump
{

    private $dumpRefs = [];

    private $hash = [];

    private $lvl = 0;

    private function __construct()
    {
    }

    /**
     * Dump an array
     *
     * @param array    $var
     * @param int|null $id
     * @param int|null $idLabel
     *
     * @return string
     */
    private function arrayDump($var, $id = null, $idLabel = null)
    {
        $dump = '';
        if (!is_null($id)) {
            if (is_null($idLabel)) {
                $idLabel = '#' . $id;
            }
            $dump .= '' . $idLabel . '';
            $dump .= '
';
        } else {
            $dump .= '';
            $dump .= '
';
        }
        foreach ($var as $key => $val) {
            $dump .= '
canHasChild($val) ? ' nuc-close' : '') . '">';
            $dump .= $this->varDump($key) . ' => ';
            $dump .= $this->varDump($val);
            $dump .= '
';
        }

        $dump .= '
';

        return $dump;
    }

    /**
     * Dump any var
     *
     * @param mixed $var
     *
     * @return string
     */
    private function varDump($var)
    {
        $this->lvl++;

        if ($this->lvl > 128) {
            $dump = '** MAX DUMP LVL **';
            $this->lvl--;

            return $dump;
        }

        $id = $this->getVarId($var);

        if (is_array($var) && isset($this->dumpRefs[$id])) {
            $dump = '';
            $dump .= 'array:' . count($var) . '  [#' . $id . '';
            $dump .= ']';
            $this->lvl--;

            return $dump;
        }

        if (is_object($var) && isset($this->dumpRefs[$id])) {
            $class = get_class($var);
            $className = $this->getClassName($class);
            $dump = '';
            $short = (preg_replace('/.*\\\\(\w+)$/', '$1', $className));
            $dump .= $short . ' {#' . $id . '';
            $dump .= '}';
            $this->lvl--;

            return $dump;
        }

        if (is_resource($var) && isset($this->dumpRefs[$id])) {
            $type = get_resource_type($var);
            $resId = intval($var);
            $label = "@$resId";
            $dump = 'resource(' . $label . ' ' . $type . ') ';
            $dump .= '{' . $label . '';
            $dump .= '}';
            $this->lvl--;

            return $dump;
        }

        if (is_null($var)) {
            $dump = 'null';
        } elseif (is_bool($var)) {
            $dump = '' . ($var ? 'true' : 'false') . '';
        } elseif (is_string($var)) {
            $dump = '"' . htmlentities($var) . '"';
        } elseif (is_scalar($var)) {
            $dump = '' . $var . '';
        } elseif (is_resource($var)) {
            $type = get_resource_type($var);
            $resId = intval($var);
            $label = "@$resId";
            $dump = 'resource(' . $label . ' ' . $type . ')';
            switch ($type) {
                case 'stream':
                    $this->dumpRefs[$id] = true;
                    $dump .= '{';
                    $dump .= $this->arrayDump(stream_get_meta_data($var), $id, $label);
                    $dump .= '}';
                    break;
                case 'process':
                    $this->dumpRefs[$id] = true;
                    $dump .= '{';
                    $dump .= $this->arrayDump(proc_get_status($var), $id, $label);
                    $dump .= '}';
                    break;
                case 'curl':
                    $this->dumpRefs[$id] = true;
                    $dump .= '{';
                    $dump .= $this->arrayDump(curl_getinfo($var), $id, $label);
                    $dump .= '}';
                    break;
            }
        } elseif (is_array($var)) {
            $dump = 'array:' . count($var) . ' [';
            if (!empty($var)) {
                if (!is_null($id)) {
                    $this->dumpRefs[$id] = true;
                }

                $dump .= $this->arrayDump($var, $id);
            }
            $dump .= ']';
        } elseif (is_object($var)) {
            $this->dumpRefs[$id] = true;

            $class = get_class($var);
            $className = $this->getClassName($class);

            $dump = '' . (preg_replace('/.*\\\\(\w+)$/', '$1', $className)) . ' ';
            $dump .= '{';

            $prop = '';
            $properties = Reflexion::getReflectionProperties($var);
            $dumpedProperties = [];
            foreach ($properties as $property) {
                $dumpedProperties[] = $name = $property->getName();
                $isStatic = $property->isStatic();
                $val = Reflexion::get($isStatic ? $class : $var, $name);

                if ($property->isPrivate()) {
                    $type = 'private';
                    $mod = '-';
                } elseif ($property->isProtected()) {
                    $type = 'protected';
                    $mod = '#';
                } else {
                    $type = 'public';
                    $mod = '+';
                }
                $ctype = str_replace(' ', '-', gettype($val));
                $vtype = $ctype === 'object' ? $this->getClassName(get_class($val)) : $ctype;
                $title = $type . ' ' . ($isStatic ? 'static ' : '') . $name . ':' . $vtype;
                $prop .= '
canHasChild($val) ? ' nuc-close' : '') . '">';
                $prop .= '' . $mod . ' ' . ($isStatic ? '::' : '') . $name . ': ';
                $prop .= $this->varDump($val);
                $prop .= '
';
            }
            foreach ($var as $key => $val) {
                if (!in_array($key, $dumpedProperties, true)) {
                    $ctype = str_replace(' ', '-', gettype($val));
                    $vtype = $ctype === 'object' ? $this->getClassName(get_class($val)) : $ctype;
                    $prop .= '
canHasChild($val) ? ' nuc-close' : '') . '">';
                    $prop .= '+ ' . $key . ': ';
                    $prop .= $this->varDump($val);
                    $prop .= '
';
                }
            }
            if (!empty($prop)) {
                $dump .= '#' . $id . '';
                $dump .= '
';
                $dump .= $prop;
                $dump .= '
';
            }
            $dump .= '}';
        } else {
            $dump = '' . gettype($var) . '';
        }

        $this->lvl--;

        return $dump;
    }

    /**
     * Return class name, and format name for anonymous class
     *
     * @param string $class
     *
     * @return string
     */
    private function getClassName($class)
    {
        if (preg_match('/^class@anonymous/', $class)) {
            return 'class@anonymous';
        }

        return $class;
    }

    /**
     * Return if a variable can has child
     *
     * @param $var
     *
     * @return bool
     */
    private function canHasChild($var)
    {
        return is_array($var) || is_object($var) || is_resource($var);
    }

    /**
     * Return id for given object|array|resource
     *
     * @param mixed $var
     *
     * @return int|null
     */
    private function getVarId($var)
    {
        if (is_object($var)) {
            $hash = spl_object_hash($var);
        } elseif (is_resource($var)) {
            $hash = intval($var) . '#resource#' . get_resource_type($var);
        } elseif (is_array($var) && $this->checkArrayRecursion($var)) {
            $hash = $this->getArrayId($var);
        }

        if (isset($hash)) {
            if (isset($this->hash[$hash])) {
                return $this->hash[$hash];
            }

            return $this->hash[$hash] = self::uid();
        }

        return null;
    }

    /**
     * Return hash id for given array
     *
     * @param array $var
     *
     * @return string
     */
    private function getArrayId(array $var)
    {
        return md5($this->genArrayHash($var));
    }

    /**
     * Generate hash id for given array
     *
     * @param array $var
     *
     * @return string
     */
    private function genArrayHash(array $var)
    {
        static $dump;

        if (!isset($dump)) {
            $dump = [];
        }

        if (in_array($var, $dump, true)) {
            return 'array recursion';
        }

        $dump[] = $var;

        $hash = [];
        foreach ($var as $k => $v) {
            if (is_object($v)) {
                $hash[$k] = spl_object_hash($v);
            } elseif (is_array($v)) {
                $hash[$k] = $this->genArrayHash($v);
            } elseif (is_resource($v)) {
                $hash[$k] = intval($v) . get_resource_type($v);
            } else {
                $hash[$k] = $v;
            }
        }

        $hash = json_encode($hash);

        array_pop($dump);

        return $hash;
    }

    /**
     * Check if an array contains any recursion
     *
     * @param array $var
     *
     * @return bool
     */
    private function checkArrayRecursion(array $var)
    {
        static $dump;

        if (!isset($dump)) {
            $dump = [];
        }

        if (in_array($var, $dump, true)) {
            return true;
        }

        $dump[] = $var;

        $return = false;

        foreach ($var as $item) {
            if (is_object($item) && $this->checkObjectRecursion($item)) {
                $return = true;
                break;
            }
            if (is_array($item) && $this->checkArrayRecursion($item)) {
                $return = true;
                break;
            }
        }

        array_pop($dump);

        return $return;
    }

    /**
     * Check if an object contains any recursion
     *
     * @param $obj
     *
     * @return bool
     */
    private function checkObjectRecursion($obj)
    {
        static $dump;

        if (!isset($dump)) {
            $dump = [];
        }

        if (in_array($obj, $dump, true)) {
            return true;
        }

        $dump[] = $obj;

        $return = false;

        $props = Reflexion::getReflectionProperties($obj);
        foreach ($props as $prop) {
            $val = Reflexion::get($obj, $prop->getName());
            if (is_array($val) && $this->checkArrayRecursion($val)) {
                $return = true;
                break;
            } elseif (is_object($val) && $this->checkObjectRecursion($val)) {
                $return = true;
                break;
            }
        }
        foreach ($obj as $val) {
            if (is_array($val) && $this->checkArrayRecursion($val)) {
                $return = true;
                break;
            } elseif (is_object($val) && $this->checkObjectRecursion($val)) {
                $return = true;
                break;
            }
        }

        array_pop($dump);

        return $return;
    }

    private static $uid = 0;

    /**
     * VarDump uid
     *
     * @return int
     */
    private static function uid()
    {
        return ++self::$uid;
    }

    /**
     * Dumps information about a variable
     *
     * @param mixed ...$vars
     */
    public static function dump(...$vars)
    {
        // We force the start of the session so that it is initialized before the first exit.
        switch (session_status()) {
            case PHP_SESSION_DISABLED:
            case PHP_SESSION_ACTIVE:
                break;
            default:
                $di = Di::getDefault();
                if ($di->has(Services::SESSION)) {
                    $di->get(Services::SESSION);
                } else {
                    session_start();
                }
        }

        foreach ($vars as $var) {
            $id = 'nuc-dump-' . self::uid();

            $dump = (new self)->varDump($var);

            echo self::outputBasic() . "
$dump
";
        }
    }

    /**
     * Return JS & CSS for dumper
     *
     * @return string
     */
    private static function outputBasic()
    {
        static $outputted;

        if (isset($outputted)) {
            return '';
        }

        $outputted = true;

        return '';
    }
}


<?php

namespace Neutrino\Foundation\Cli\Tasks;

use Neutrino\Cli\Output\Decorate;
use Neutrino\Cli\Output\Group;
use Neutrino\Cli\Output\Helper;
use Neutrino\Cli\Task;
use Neutrino\Constants\Services;
use Neutrino\Support\Arr;
use Phalcon\Cli\Router\Route;

/**
 * Class ListTask
 *
 * @package Neutrino\Foundation\Cli
 */
class ListTask extends Task
{
    protected $reflections = [];
    protected $scanned     = [];
    protected $describes   = [];

    /**
     * List all commands available.
     *
     * @description List all commands available.
     */
    public function mainAction()
    {
        $this->displayHeader();

        $routes = $this->router->getRoutes();

        $delimiter = Route::getDelimiter();
        foreach ($routes as $route) {
            /** @var Route $route */
            // Default route
            $pattern = $route->getPattern();
            if ($pattern === "#^(?:$delimiter)?([a-zA-Z0-9\\_\\-]+)[$delimiter]{0,1}$#" ||
                $pattern === "#^(?:$delimiter)?([a-zA-Z0-9\\_\\-]+)$delimiter([a-zA-Z0-9\\.\\_]+)($delimiter.*)*$#"
            ) {
                continue;
            }

            $this->describeRoute($route);
        }

        $datas = [];

        foreach ($this->describes as $describe) {
            if (isset($describe['__exception'])) {
                $datas[$describe['cmd']] = Decorate::error(explode(PHP_EOL, $describe['__exception'], 2)[0]);
            } else {
                $datas[$describe['cmd']] = explode(PHP_EOL, $describe['description'], 2)[0];
            }
        }

        $this->notice('Available Commands :');

        (new Group($this->output, $datas, Group::SORT_ASC))->display();
    }

    /**
     * Describe a \Phalcon\Cli\Router\Route
     *
     * @param \Phalcon\Cli\Router\Route $route
     */
    protected function describeRoute(Route $route)
    {
        $paths = $route->getPaths();

        $class = $paths['task'];

        $action = Arr::fetch($paths, 'action', 'main') . $this->dispatcher->getActionSuffix();

        $this->scanned[$class . '::' . $action] = true;

        $compiled = Helper::describeRoutePattern($route, true);

        $this->describe($compiled, $class, $action);
    }

    /**
     * @param string $pattern
     * @param string $class
     * @param string $action
     */
    protected function describe($pattern, $class, $action)
    {
        $infos = Helper::getTaskInfos($class, $action);

        if (!empty($infos['options'])) {
            $infos['options'] = implode(', ', $infos['options']);
        }
        if (!empty($infos['arguments'])) {
            $infos['arguments'] = implode(', ', $infos['arguments']);
        }

        if (isset($infos['__exception'])) {
            $infos['cmd'] = Decorate::error($pattern);
        } else {
            $infos['cmd'] = Decorate::info($pattern);
        }

        $this->describes[] = $infos;
    }

    protected function displayHeader()
    {
        $this->{Services::APP}->displayNeutrinoVersion();
        $this->notice('Usage :');
        $this->line('  command [options] [arguments]');
        $this->line('');
        $this->notice('Options :');
        $this->info('  -h, --help                     Display this help message');
        $this->info('  -q, --quiet                    Do not output any message');
        $this->info('  -s, --stats                    Display timing and memory usage information');
        $this->info('      --colors                   Force Colors output');
        $this->info('      --no-colors                Disable Colors output');
        $this->line('');
    }
}


<?php

namespace Neutrino\Cli\Question;

/**
 * Class ConfirmationQuestion
 *
 * @package Neutrino\Cli\Question
 */
class ConfirmationQuestion extends Question
{
    protected $answerRegex;

    /**
     * ConfirmationQuestion constructor.
     *
     * @param string $question
     * @param bool   $default
     * @param string $trueAnswerRegex
     */
    public function __construct($question, $default = true, $trueAnswerRegex = '/^(?:y|o)/i')
    {
        parent::__construct($question, (bool)$default);

        $this->answerRegex = $trueAnswerRegex;
    }

    /**
     * @param $response
     *
     * @return bool|null|string
     */
    public function normalize($response)
    {
        if (is_bool($response)) {
            return $response;
        }

        $response = parent::normalize($response);

        if ($response === null || $response === '') {
            return $this->default;
        }

        return (bool)preg_match($this->answerRegex, $response);
    }
}


<?php

namespace Igniter\Flame\Support;

use Exception;
use Igniter\Flame\Filesystem\Filesystem;

class ClassLoader
{
    /**
     * The filesystem instance.
     * @var \Igniter\Flame\Filesystem\Filesystem
     */
    public $files;

    /**
     * The base path.
     * @var string
     */
    public $basePath;

    /**
     * The manifest path.
     * @var string|null
     */
    public $manifestPath;

    /**
     * The loaded manifest array.
     * @var array
     */
    public $manifest;

    /**
     * The registered directories.
     * @var array
     */
    protected $directories = [];

    /**
     * Indicates if a loader has been registered.
     * @var bool
     */
    protected $registered = FALSE;

    protected $manifestIsDirty = FALSE;

    public function __construct(Filesystem $files, $basePath, $manifestPath)
    {
        $this->files = $files;
        $this->basePath = $basePath;
        $this->manifestPath = $manifestPath;
    }

    /**
     * Register loader with SPL autoloader stack.
     * @return void
     */
    public function register()
    {
        if ($this->registered) {
            return;
        }

        $this->loadManifest();

        $this->registered = spl_autoload_register([$this, 'loadClass']);
    }

    /**
     * Store the manifest array by writing it to filesystem.
     *
     * @return void
     */
    public function store()
    {
        if (!$this->manifestIsDirty) {
            return;
        }

        $this->write($this->manifest);
    }

    /**
     * Loads the class file for a given class name.
     *
     * @param string $class The fully-qualified class name.
     *
     * @return mixed The mapped file name on success, or boolean false on
     * failure.
     */
    public function loadClass($class)
    {
        if (
            isset($this->manifest[$class]) &&
            $this->isRealFilePath($path = $this->manifest[$class])
        ) {
            require_once $this->basePath.DIRECTORY_SEPARATOR.$path;

            return TRUE;
        }

        // Try to load a mapped file for the prefix and relative class
        if ($mappedFile = $this->loadMappedClass($class)) {
            return $mappedFile;
        }

        // never found a mapped file
        return FALSE;
    }

    /**
     * Gets all the directories registered with the loader.
     *
     * @return array
     */
    public function getDirectories()
    {
        return $this->directories;
    }

    /**
     * Add directories to the class loader.
     *
     * @param  string|array $directories
     *
     * @return void
     */
    public function addDirectories($directories)
    {
        $this->directories = array_merge($this->directories, (array)$directories);

        $this->directories = array_unique($this->directories);
    }

    /**
     * Remove directories from the class loader.
     *
     * @param  string|array $directories
     *
     * @return void
     */
    public function removeDirectories($directories = null)
    {
        if (is_null($directories)) {
            $this->directories = [];
        }
        else {
            $directories = (array)$directories;

            $this->directories = array_filter($this->directories, function ($directory) use ($directories) {
                return !in_array($directory, $directories);
            });
        }
    }

    /**
     * Get the normal file name for a class.
     *
     * @param  string $class
     *
     * @return array
     */
    protected function normalizeClass($class)
    {
        // Strip first slash
        $class = ltrim($class, '\\');

        // Work backwards through the namespace names of the fully-qualified
        // class name to find a mapped file name
        $pos = strrpos($class, '\\');

        // Retain the trailing namespace separator in the prefix
        $directory = substr($class, 0, $pos + 1);

        // The rest is the relative class name
        $relativeClass = substr($class, $pos + 1);
        $directory = str_replace(['\\', '.'], DIRECTORY_SEPARATOR, $directory);

        $directory = trim($directory, DIRECTORY_SEPARATOR);

        $lowerClass = strtolower($directory).DIRECTORY_SEPARATOR.$relativeClass;
        $upperClass = $directory.DIRECTORY_SEPARATOR.$relativeClass;

        return [$lowerClass, $upperClass];
    }

    /**
     * Load the mapped class for a directory prefix and relative class.
     *
     * @param string $class The class name.
     *
     * @return mixed bool false if no mapped file can be loaded, or the
     * name of the mapped file that was loaded.
     */
    protected function loadMappedClass($class)
    {
        list($lowerClass, $upperClass) = $this->normalizeClass($class);

        // Look through registered directories
        foreach ($this->directories as $directory) {

            // If the mapped class exists, require it
            if ($this->isRealFilePath($path = $directory.DIRECTORY_SEPARATOR.$lowerClass.'.php')) {
                $this->requireClass($class, $path);

                return $path;
            }

            if ($this->isRealFilePath($path = $directory.DIRECTORY_SEPARATOR.$upperClass.'.php')) {
                $this->requireClass($class, $path);

                return TRUE;
            }
        }

        // never found it
        return FALSE;
    }

    /**
     * Determine if a relative path to a file exists and is real
     *
     * @param  string $path
     *
     * @return bool
     */
    protected function isRealFilePath($path)
    {
        return is_file(realpath($this->basePath.DIRECTORY_SEPARATOR.$path));
    }

    /**
     * If a file exists, require it from the file system.
     *
     * @param $class
     * @param string $path The file to require.
     *
     * @return void True if the file exists, false if not.
     */
    protected function requireClass($class, $path)
    {
        require_once $this->basePath.DIRECTORY_SEPARATOR.$path;

        $this->manifest[$class] = $path;

        $this->manifestIsDirty = TRUE;
    }

    /**
     * Load the manifest into memory.
     *
     * @return void
     */
    protected function loadManifest()
    {
        if (!is_null($this->manifest)) {
            return;
        }

        if (file_exists($this->manifestPath)) {
            try {
                $this->manifest = $this->files->getRequire($this->manifestPath);

                if (!is_array($this->manifest)) {
                    $this->manifest = [];
                }
            } catch (Exception $ex) {
                $this->manifest = [];
            }
        }
        else {
            $this->manifest = [];
        }
    }

    /**
     * Write the manifest array to filesystem.
     *
     * @param  array $manifest
     *
     * @return void
     * @throws \Exception
     */
    protected function write(array $manifest)
    {
        if (!is_writable($path = dirname($this->manifestPath))) {
            throw new Exception('The '.$path.' directory must be present and writable.');
        }

        $this->files->put(
            $this->manifestPath, '<?php return '.var_export($manifest, TRUE).';'
        );
    }
}


<?php

namespace Neutrino\Database\Schema\Dialect;

use Phalcon\Db\Dialect as DbDialect;
use Phalcon\Db\DialectInterface as DbDialectInterface;
use Neutrino\Database\Schema\Dialect as SchemaDialect;
use Neutrino\Database\Schema\DialectInterface as SchemaDialectInterface;

/**
 * Class Factory
 *
 * @package Neutrino\Database\Schema\Dialect
 */
final class Factory
{
    /**
     * @param \Phalcon\Db\DialectInterface $dialect
     *
     * @return \Neutrino\Database\Schema\DialectInterface
     */
    public static function create(DbDialectInterface $dialect)
    {
        if ($dialect instanceof SchemaDialectInterface) {
            return $dialect;
        } elseif ($dialect instanceof DbDialect\Mysql) {
            return new SchemaDialect\Mysql($dialect);
        } elseif ($dialect instanceof DbDialect\Postgresql) {
            return new SchemaDialect\Postgresql($dialect);
        } elseif ($dialect instanceof DbDialect\Sqlite) {
            return new SchemaDialect\Sqlite($dialect);
        }

        return new SchemaDialect\Wrapper($dialect);
    }
}


<?php

namespace Neutrino\Database\Cli\Tasks;

use Neutrino\Database\Schema\Builder;

/**
 * Class FreshTask
 *
 * @package Neutrino\Database\Cli\Tasks
 */
class FreshTask extends BaseTask
{
    /**
     * @description Drop all tables and re-run all migrations.
     *
     * @option -f, --force Force the operation to run when in production.
     * @option --path The path of migrations files to be executed.
     * @option --pretend : Dump the SQL queries that would be run.
     */
    public function mainAction()
    {
        if (!$this->confirmToProceed()) {
            return;
        }

        $this->dropAllTables();

        $this->info('Dropped all tables successfully.');

        $this->callTask(MigrateTask::class, 'main', $this->arguments, $this->options);
    }

    /**
     * Drop all of the database tables.
     *
     * @return void
     */
    protected function dropAllTables()
    {
        (new Builder())->dropAllTables();
    }
}


<?php

namespace Neutrino\View\Engines\Volt\Compiler\Filters;

use Neutrino\View\Engines\Volt\Compiler\FilterExtend;

/**
 * Class RoundFilter
 *
 * @package App\Core\View\Engines\Volt\Filters
 */
class RoundFilter extends FilterExtend
{
    /*
    #define PHVOLT_T_INTEGER 258
    #define PHVOLT_T_DOUBLE 259
    #define PHVOLT_T_STRING 260
    #define PHVOLT_T_NULL 261
    #define PHVOLT_T_FALSE 262
    #define PHVOLT_T_TRUE 263
     *
     */
    /**
     * @param string $resolvedArgs
     * @param array $exprArgs
     *
     * @return string|null
     */
    public function compileFilter($resolvedArgs, $exprArgs)
    {
        $value = isset($exprArgs[0]['expr']['value']) ? $exprArgs[0]['expr']['value'] : $resolvedArgs;

        switch (isset($exprArgs[1]['expr']['type']) ? $exprArgs[1]['expr']['type'] : null) {
            case 260:
                switch (isset($exprArgs[1]['expr']['value']) ? $exprArgs[1]['expr']['value'] : null) {
                    case 'floor':
                        return "floor($value)";
                    case 'ceil':
                        return "ceil($value)";
                }
        }

        $precision = isset($exprArgs[1]['expr']['value']) ? $exprArgs[1]['expr']['value'] : 0;

        switch (isset($exprArgs[2]['expr']['value']) ? $exprArgs[2]['expr']['value'] :  null) {
            case 'floor':
                return "floor($value*(10**$precision))/(10**$precision)";
            case 'ceil':
                return "ceil($value*(10**$precision))/(10**$precision)";
        }

        return "round($value, $precision)";
    }
}


<?php namespace Igniter\Flame\Translation;

use Illuminate\Translation\FileLoader as FileLoaderBase;

class FileLoader extends FileLoaderBase
{
    /**
     * Translation driver instance.
     *
     * @var Contracts\Driver[]
     */
    protected $drivers = [];

    public function load($locale, $group, $namespace = null)
    {
        $lines = parent::load($locale, $group, $namespace);

        if (is_null($namespace) || $namespace == '*') {
            return $lines;
        }

        $driverLines = $this->loadFromDrivers($locale, $group, $namespace);

        return array_replace_recursive($lines, $driverLines);
    }

    /**
     * Get storage driver.
     *
     * @param $locale
     * @param $group
     * @param null $namespace
     *
     * @return Contracts\Driver
     */
    public function loadFromDrivers($locale, $group, $namespace = null)
    {
        return collect($this->drivers)->map(function ($className) {
            return app($className);
        })->mapWithKeys(function (Contracts\Driver $driver) use ($locale, $group, $namespace) {
            return $driver->load($locale, $group, $namespace);
        })->toArray();
    }

    public function addDriver($driver)
    {
        $this->drivers[] = $driver;
    }

    /**
     * Load a namespaced translation group.
     *
     * @param  string $locale
     * @param  string $group
     * @param  string $namespace
     *
     * @return array
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    protected function loadNamespaced($locale, $group, $namespace)
    {
        if (isset($this->hints[$namespace])) {
            $lines = $this->loadPath($this->hints[$namespace], $locale, $group);

            return $this->loadNamespaceOverrides($lines, $locale, $group, $namespace);
        }

        return [];
    }

    /**
     * Load a local namespaced translation group for overrides.
     *
     * @param  array $lines
     * @param  string $locale
     * @param  string $group
     * @param  string $namespace
     *
     * @return array
     * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
     */
    protected function loadNamespaceOverrides(array $lines, $locale, $group, $namespace)
    {
        $file = "{$this->path}/vendor/{$namespace}/{$locale}/{$group}.php";

        if ($this->files->exists($file)) {
            return array_replace_recursive($lines, $this->files->getRequire($file));
        }

        return $lines;
    }

    /**
     * Load a locale from a given path.
     *
     * @param  string $path
     * @param  string $locale
     * @param  string $group
     *
     * @return array
     */
    protected function loadPath($path, $locale, $group)
    {
        return collect(['_lang.php', '.php'])
            ->reduce(function ($output, $ext) use ($path, $locale, $group) {
                if ($this->files->exists($full = "{$path}/{$locale}/{$group}{$ext}")) {
                    $output = array_merge($output, $this->files->getRequire($full));
                }

                return $output;
            }, []);
    }
}


<?php

namespace Igniter\Flame\Setting;

use Illuminate\Cache\Repository;
use Illuminate\Database\DatabaseManager;
use Illuminate\Support\Arr;
use UnexpectedValueException;

class DatabaseSettingStore extends SettingStore
{
    /**
     * The database connection instance.
     * @var \Illuminate\Database\DatabaseManager
     */
    protected $db;

    /**
     * The cache instance.
     * @var \Illuminate\Cache\Repository
     */
    protected $cache;

    protected $cacheKey;

    /**
     * The table to query from.
     * @var string
     */
    protected $table = 'settings';

    /**
     * The key column name to query from.
     * @var string
     */
    protected $keyColumn = 'item';

    /**
     * The value column name to query from.
     * @var string
     */
    protected $valueColumn = 'value';

    /**
     * Any query constraints that should be applied.
     * @var \Closure|null
     */
    protected $queryConstraint;

    /**
     * Any extra columns that should be added to the rows.
     * @var array
     */
    protected $extraColumns = [];

    /**
     * @param \Illuminate\Database\DatabaseManager $db
     * @param \Illuminate\Cache\Repository $cache
     */
    public function __construct(DatabaseManager $db, Repository $cache)
    {
        $this->db = $db;
        $this->cache = $cache;
    }

    /**
     * Set the table to query from.
     *
     * @param string $table
     */
    public function setTable($table)
    {
        $this->table = $table;
    }

    /**
     * Set the key column name to query from.
     *
     * @param $keyColumn
     */
    public function setKeyColumn($keyColumn)
    {
        $this->keyColumn = $keyColumn;
    }

    /**
     * Set the value column name to query from.
     *
     * @param $valueColumn
     */
    public function setValueColumn($valueColumn)
    {
        $this->valueColumn = $valueColumn;
    }

    /**
     * Set the query constraint.
     *
     * @param \Closure $callback
     */
    public function setConstraint(\Closure $callback)
    {
        $this->items = [];
        $this->loaded = FALSE;
        $this->queryConstraint = $callback;
    }

    /**
     * Set extra columns to be added to the rows.
     *
     * @param array $columns
     */
    public function setExtraColumns(array $columns)
    {
        $this->extraColumns = $columns;
    }

    /**
     * {@inheritdoc}
     */
    public function forget($key)
    {
        parent::forget($key);

        // because the database store cannot store empty arrays, remove empty
        // arrays to keep data consistent before and after saving
        $segments = explode('.', $key);
        array_pop($segments);

        while ($segments) {
            $segment = implode('.', $segments);

            // non-empty array - exit out of the loop
            if ($this->get($segment)) {
                break;
            }

            // remove the empty array and move on to the next segment
            $this->forget($segment);
            array_pop($segments);
        }
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $data)
    {
        $keysQuery = $this->newQuery();

        $keys = $keysQuery->pluck($this->valueColumn, $this->keyColumn);
        $insertData = array_dot($data);
        $updateData = [];
        $deleteKeys = [];

        foreach ($keys as $key => $sort) {
            if (isset($insertData[$key])) {
                if ($sort != $insertData[$key])
                    $updateData[$key] = $insertData[$key];
            }
            else {
                $deleteKeys[] = $key;
            }
            unset($insertData[$key]);
        }

        foreach ($updateData as $key => $value) {
            $this->newQuery()
                 ->where($this->keyColumn, '=', $key)
                 ->update([$this->valueColumn => $value]);
        }

        if ($insertData) {
            $this->newQuery(TRUE)
                 ->insert($this->prepareInsertData($insertData));
        }

        if ($deleteKeys) {
            $this->newQuery()
                 ->whereIn($this->keyColumn, $deleteKeys)
                 ->delete();
        }

        $this->flushCache();
    }

    /**
     * Transforms settings data into an array ready to be insterted into the
     * database. Call array_dot on a multidimensional array before passing it
     * into this method!
     *
     * @param  array $data Call array_dot on a multidimensional array before passing it into this method!
     *
     * @return array
     */
    protected function prepareInsertData(array $data)
    {
        $dbData = [];

        if ($this->extraColumns) {
            foreach ($data as $key => $value) {
                $dbData[] = array_merge(
                    $this->extraColumns,
                    [$this->keyColumn => $key, $this->valueColumn => $this->parseInsertKeyValue($value)]
                );
            }
        }
        else {
            foreach ($data as $key => $value) {
                $dbData[] = [$this->keyColumn => $key, $this->valueColumn => $this->parseInsertKeyValue($value)];
            }
        }

        return $dbData;
    }

    /**
     * {@inheritdoc}
     */
    protected function read()
    {
        $collection = $this->cacheCallback(function () {
            return $this->newQuery()->get();
        });

        return $this->parseReadData($collection);
    }

    /**
     * Parse data coming from the database.
     *
     * @param  \Illuminate\Support\Collection $data
     *
     * @return array
     */
    protected function parseReadData($data)
    {
        $results = [];

        foreach ($data as $row) {
            if (is_array($row)) {
                $key = $row[$this->keyColumn];
                $value = $this->parseKeyValue($row[$this->valueColumn]);
            }
            elseif (is_object($row)) {
                $key = $row->{$this->keyColumn};
                $value = $this->parseKeyValue($row->{$this->valueColumn});
            }
            else {
                throw new UnexpectedValueException('Expected array or object, got '.gettype($row));
            }

            Arr::set($results, $key, $value);
        }

        return $results;
    }

    /**
     * Create a new query builder instance.
     *
     * @param  $insert  boolean  Whether the query is an insert or not.
     *
     * @return \Illuminate\Database\Query\Builder
     */
    protected function newQuery($insert = FALSE)
    {
        $query = $this->db->table($this->table);

        if (!$insert) {
            foreach ($this->extraColumns as $key => $value) {
                $query->where($key, '=', $value);
            }
        }

        if ($this->queryConstraint !== null) {
            $callback = $this->queryConstraint;
            $callback($query, $insert);
        }

        return $query;
    }

    protected function parseKeyValue($value)
    {
        $_value = @unserialize($value);
        if ($_value === FALSE && $_value !== 'b:0;') {
            return $value;
        }

        return $_value;
    }

    protected function parseInsertKeyValue($value)
    {
        return is_scalar($value) ? $value : null;
    }

    //
    // Cache
    //

    /**
     * @return mixed
     */
    public function getCacheKey()
    {
        return $this->cacheKey;
    }

    /**
     * @param mixed $cacheKey
     */
    public function setCacheKey($cacheKey)
    {
        $this->cacheKey = $cacheKey;
    }

    protected function flushCache()
    {
        if ($cacheKey = $this->getCacheKey()) {
            $this->cache->forget($this->getCacheKey());
            $this->loaded = FALSE;
        }
    }

    protected function cacheCallback(\Closure $callback)
    {
        if ($cacheKey = $this->getCacheKey())
            return $this->cache->rememberForever($cacheKey, $callback);

        return $callback();
    }
}


<?php

namespace Neutrino\HttpClient;

use Neutrino\HttpClient\Contract\Parser\Parserize;

/**
 * Class Response
 */
class Response
{
    /** @var int|null */
    protected $code;

    /** @var Header */
    protected $header;

    /** @var string */
    protected $body = '';

    /** @var mixed */
    protected $data;

    /** @var int|null */
    protected $errorCode;

    /** @var string|null */
    protected $error;

    /** @var mixed */
    protected $providerDatas;

    /**
     * Response constructor.
     *
     * @param \Neutrino\HttpClient\Header $header
     */
    public function __construct(Header $header = null)
    {
        $this->setHeader($header === null ? new Header() : $header);
    }

    /**
     * Check if the HTTP Response is valid (2xx)
     *
     * @return bool
     */
    public function isOk()
    {
        return $this->code >= 200 && $this->code < 300;
    }

    /**
     * Check if an HTTP Response is a redirection (3xx)
     *
     * @return bool
     */
    public function isRedirect()
    {
        return $this->code >= 300 && $this->code < 400;
    }

    /**
     * Check if an HTTP error append (4xx, 5xx)
     *
     * @return bool
     */
    public function isFail()
    {
        return $this->code >= 400;
    }

    /**
     * Check if an CURL error append
     *
     * @return bool
     */
    public function isError()
    {
        return isset($this->errorCode) && ($this->errorCode !== null || $this->errorCode !== 0);
    }

    /**
     * @param Parserize|string $parser
     *
     * @return $this
     * @throws \RuntimeException
     */
    public function parse($parser)
    {
        if (is_string($parser)) {
            $parser = new $parser;
        }

        if ($parser instanceof Parserize) {
            $this->data = $parser->parse($this->body);

            return $this;
        }

        throw new \RuntimeException(__METHOD__ . ': $parserize must implement ' . Parserize::class);
    }

    /**
     * @return int|null
     */
    public function getCode()
    {
        return $this->code;
    }

    /**
     * @param int|null $code
     *
     * @return Response
     */
    public function setCode($code)
    {
        $this->code = $code;

        return $this;
    }

    /**
     * @return \Neutrino\HttpClient\Header
     */
    public function getHeader()
    {
        return $this->header;
    }

    /**
     * @param \Neutrino\HttpClient\Header $header
     *
     * @return Response
     */
    public function setHeader(Header $header)
    {
        $this->header = $header;

        return $this;
    }

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

    /**
     * @param string $body
     *
     * @return Response
     */
    public function setBody($body)
    {
        $this->body = $body;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * @return null|string
     */
    public function getError()
    {
        return $this->error;
    }

    /**
     * @param null|string $error
     *
     * @return Response
     */
    public function setError($error)
    {
        $this->error = $error;

        return $this;
    }

    /**
     * @return int|null
     */
    public function getErrorCode()
    {
        return $this->errorCode;
    }

    /**
     * @param int|null $errorCode
     *
     * @return Response
     */
    public function setErrorCode($errorCode)
    {
        $this->errorCode = $errorCode;

        return $this;
    }

    /**
     * @return mixed
     */
    public function getProviderDatas()
    {
        return $this->providerDatas;
    }

    /**
     * @param mixed $providerDatas
     *
     * @return Response
     */
    public function setProviderDatas($providerDatas)
    {
        $this->providerDatas = $providerDatas;

        return $this;
    }
}


<?php

namespace Igniter\Flame\Scaffold\Console;

use Igniter\Flame\Scaffold\GeneratorCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;

class CreateController extends GeneratorCommand
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'create:controller';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Creates a new controller.';

    /**
     * The type of class being generated.
     *
     * @var string
     */
    protected $type = 'Controller';

    /**
     * A mapping of stub to generated file.
     *
     * @var array
     */
    protected $stubs = [
        'controller/controller.stub' => 'controllers/{{studly_name}}.php',
        'controller/index.stub' => 'views/{{lower_name}}/index.php',
        'controller/create.stub' => 'views/{{lower_name}}/create.php',
        'controller/edit.stub' => 'views/{{lower_name}}/edit.php',
        'controller/preview.stub' => 'views/{{lower_name}}/preview.php',
    ];

    /**
     * Prepare variables for stubs.
     *
     * return @array
     */
    protected function prepareVars()
    {
        if (!$code = $this->getExtensionInput()) {
            $this->error('Invalid extension name, Example name: AuthorName.ExtensionName');

            return;
        }

        list($author, $extension) = $code;
        $controller = $this->argument('controller');

        $this->vars = [
            'extension' => $extension,
            'lower_extension' => strtolower($extension),
            'title_extension' => title_case($extension),
            'studly_extension' => studly_case($extension),

            'author' => $author,
            'lower_author' => strtolower($author),
            'title_author' => title_case($author),
            'studly_author' => studly_case($author),

            'name' => $controller,
            'lower_name' => strtolower($controller),
            'title_name' => title_case($controller),
            'studly_name' => studly_case($controller),
            'singular_name' => str_singular($controller),
            'studly_singular_name' => studly_case(str_singular($controller)),
            'snake_singular_name' => snake_case(str_singular($controller)),
            'plural_name' => str_plural($controller),
            'studly_plural_name' => studly_case(str_plural($controller)),
            'snake_plural_name' => snake_case(str_plural($controller)),
        ];
    }

    /**
     * Get the console command arguments.
     *
     * @return array
     */
    protected function getArguments()
    {
        return [
            ['extension', InputArgument::REQUIRED, 'The name of the extension to create. Eg: IgniterLab.Demo'],
            ['controller', InputArgument::REQUIRED, 'The name of the model. Eg: Blocks'],
        ];
    }

    /**
     * Get the console command options.
     *
     * @return array
     */
    protected function getOptions()
    {
        return [
            ['force', null, InputOption::VALUE_NONE, 'Overwrite existing files with generated ones.'],
        ];
    }
}


<?php

namespace Neutrino\Cli\Output;

/**
 * Class Decorate
 *
 * @package Neutrino\Cli\Output
 *
 * @author  Fabien Potencier <fabien@symfony.com>
 * @see     https://github.com/symfony/console/blob/3.0/Formatter/OutputFormatterStyle.php
 *
 * Transformed from symfony/console.
 */
class Decorate
{
    private static $availableForegroundColors = [
        'black'   => ['set' => 30, 'unset' => 39],
        'red'     => ['set' => 31, 'unset' => 39],
        'green'   => ['set' => 32, 'unset' => 39],
        'yellow'  => ['set' => 33, 'unset' => 39],
        'blue'    => ['set' => 34, 'unset' => 39],
        'magenta' => ['set' => 35, 'unset' => 39],
        'cyan'    => ['set' => 36, 'unset' => 39],
        'white'   => ['set' => 37, 'unset' => 39],
        'default' => ['set' => 39, 'unset' => 39],
    ];

    private static $availableBackgroundColors = [
        'black'   => ['set' => 40, 'unset' => 49],
        'red'     => ['set' => 41, 'unset' => 49],
        'green'   => ['set' => 42, 'unset' => 49],
        'yellow'  => ['set' => 43, 'unset' => 49],
        'blue'    => ['set' => 44, 'unset' => 49],
        'magenta' => ['set' => 45, 'unset' => 49],
        'cyan'    => ['set' => 46, 'unset' => 49],
        'white'   => ['set' => 47, 'unset' => 49],
        'default' => ['set' => 49, 'unset' => 49],
    ];

    private static $availableOptions = [
        'bold'       => ['set' => 1, 'unset' => 22],
        'underscore' => ['set' => 4, 'unset' => 24],
        'blink'      => ['set' => 5, 'unset' => 25],
        'reverse'    => ['set' => 7, 'unset' => 27],
        'conceal'    => ['set' => 8, 'unset' => 28],
    ];

    private static $hasColorSupport;

    /**
     * Check if console has color support
     *
     * @return bool
     */
    private static function hasColorSupport()
    {
        if (isset(self::$hasColorSupport)) {
            return self::$hasColorSupport;
        }

        if (DIRECTORY_SEPARATOR === '\\') {
            return self::$hasColorSupport =
                (10 == PHP_WINDOWS_VERSION_MAJOR && PHP_WINDOWS_VERSION_BUILD >= 10586)
                || false !== getenv('ANSICON')
                || 'ON' === getenv('ConEmuANSI')
                || 'xterm' === getenv('TERM');
        }

        return self::$hasColorSupport = function_exists('posix_isatty') && @posix_isatty(STDOUT);
    }

    /**
     * Force color support.
     *
     * @param bool $support
     */
    public static function setColorSupport($support)
    {
        self::$hasColorSupport = $support;
    }

    /**
     * Applies the style to a given text.
     *
     * @param string $text The text to style=
     * @param null   $foreground
     * @param null   $background
     * @param array  $options
     *
     * @return string
     */
    public static function apply($text, $foreground = null, $background = null, array $options = [])
    {
        if (!self::hasColorSupport()) {
            return $text;
        }

        $setCodes   = [];
        $unsetCodes = [];

        if (null !== $foreground) {
            $setCodes[]   = self::$availableForegroundColors[$foreground]['set'];
            $unsetCodes[] = self::$availableForegroundColors[$foreground]['unset'];
        }
        if (null !== $background) {
            $setCodes[]   = self::$availableBackgroundColors[$background]['set'];
            $unsetCodes[] = self::$availableBackgroundColors[$background]['unset'];
        }
        if (!empty($options)) {
            foreach ($options as $option) {
                $setCodes[]   = self::$availableOptions[$option]['set'];
                $unsetCodes[] = self::$availableOptions[$option]['unset'];
            }
        }

        if (0 === count($setCodes)) {
            return $text;
        }

        return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
    }

    /**
     * Decorate a string as information output.
     *
     * @param string $str
     *
     * @return string
     */
    public static function info($str)
    {
        return self::apply($str, 'green');
    }

    /**
     * Decorate a string as notice output.
     *
     * @param string $str
     *
     * @return string
     */
    public static function notice($str)
    {
        return self::apply($str, 'yellow');
    }

    /**
     * Decorate a string as warning output.
     *
     * @param string $str
     *
     * @return string
     */
    public static function warn($str)
    {
        return self::apply($str, 'yellow', null, ['reverse']);
    }

    /**
     * Decorate a string as error output.
     *
     * @param string $str
     *
     * @return string
     */
    public static function error($str)
    {
        return self::apply($str, 'black', 'red');
    }

    /**
     * Decorate a string as question output.
     *
     * @param string $str
     *
     * @return string
     */
    public static function question($str)
    {
        return self::apply($str, 'black', 'cyan');
    }
}


<?php

namespace Neutrino\View\Engines\Volt\Compiler\Filters;

use Neutrino\View\Engines\Volt\Compiler\FilterExtend;

/**
 * Class SplitFilter
 *
 * @package Neutrino\View\Engines\Volt\Compiler\Filters
 */
class SplitFilter extends FilterExtend
{

    /**
     * @param string $resolvedArgs
     * @param array  $exprArgs
     *
     * @return string|null
     */
    public function compileFilter($resolvedArgs, $exprArgs)
    {
        $value = isset($exprArgs[0]['expr']['value']) ? $exprArgs[0]['expr']['value'] : $resolvedArgs;

        $separator = isset($exprArgs[1]['expr']['value'])
            ? $exprArgs[1]['expr']['value']
            : '';

        if (empty($separator)) {

            $length = isset($exprArgs[2]['expr']['value'])
                ? $exprArgs[2]['expr']['value']
                : '1';

            return 'str_split(' . $value . ', ' . intval($length) . ')';
        }

        if(isset($exprArgs[2]['expr']['value'])){
            return 'explode(' . var_export($separator, true) . ', ' . $value . ', ' . intval($exprArgs[2]['expr']['value']) . ')';
        }

        return 'explode(' . var_export($separator, true) . ', ' . $value . ')';
    }
}


<?php

namespace Neutrino\Database\Migrations\Storage;

use Neutrino\Support\Arr;

/**
 * Class FileStorage
 *
 * @package Neutrino\Database\Migrations\Storage
 */
class FileStorage implements StorageInterface
{
    private $data;

    /**
     * Get the ran migrations.
     *
     * @return array
     */
    public function getRan()
    {
        $data = $this->getData();

        array_multisort(
            array_column($data, 'batch'), SORT_ASC,
            array_column($data, 'migration'), SORT_ASC,
            $data
        );

        return Arr::pluck($data, 'migration');
    }

    /**
     * Get list of migrations.
     *
     * @param  int $steps
     *
     * @return array
     */
    public function getMigrations($steps)
    {
        $data = $this->getData();

        $data = array_filter($data, function ($datum) {
            return (int)$datum['batch'] >= 1;
        });

        array_multisort(
            array_column($data, 'batch'), SORT_DESC,
            array_column($data, 'migration'), SORT_DESC,
            $data
        );

        return array_slice($data, 0, $steps);
    }

    /**
     * Get the last migration batch.
     *
     * @return array
     */
    public function getLast()
    {
        $data = $this->getData();

        if(empty($data)){
            return [];
        }

        $lastBatch = $this->getLastBatchNumber();

        $data = array_filter($data, function ($datum) use ($lastBatch) {
            return (int)$datum['batch'] = $lastBatch;
        });

        $migrate_at = array_column($data, 'migration');

        arsort($migrate_at);

        reset($migrate_at);

        return [$data[key($migrate_at)]];
    }

    /**
     * Log that a migration was run.
     *
     * @param string $migration Migration Name
     * @param int    $batch     Batch number
     *
     * @throws \Exception
     * @return void
     */
    public function log($migration, $batch)
    {
        $data = $this->getData();

        $data[] = ['migration' => $migration, 'batch' => $batch];

        $this->setData($data);
    }

    /**
     * Remove a migration from the log.
     *
     * @param string $migration Migration Name
     *
     * @throws \Exception
     * @return void
     */
    public function delete($migration)
    {
        $data = $this->getData();

        foreach ($data as $key => $datum) {
            if ($datum['migration'] == $migration) {
                unset($data[$key]);
            }
        }

        $this->setData($data);
    }

    /**
     * @return int
     */
    public function getLastBatchNumber()
    {
        $data = $this->getData();

        if(empty($data)){
            return 0;
        }

        $batch = array_column($data, 'batch');

        rsort($batch);

        reset($batch);

        return $batch[key($batch)];
    }

    /**
     * @return int
     */
    public function getNextBatchNumber()
    {
        return $this->getLastBatchNumber() + 1;
    }

    /**
     * @return bool
     */
    public function createStorage()
    {
        if ($this->storageExist()) {
            return true;
        }

        return file_put_contents($this->getFilePath(), '[]') === 2;
    }

    /**
     * @return bool
     */
    public function storageExist()
    {
        return file_exists($this->getFilePath());
    }

    private function getFilePath()
    {
        return BASE_PATH . '/migrations/.migrations.dat';
    }

    private function getData()
    {
        if (!isset($this->data)) {
            if ($this->storageExist()) {
                $this->data = (array)json_decode(file_get_contents($this->getFilePath()), true);
            } else {
                $this->data = [];
            }
        }

        return $this->data;
    }

    private function setData($data)
    {
        $this->data = $data;

        file_put_contents($this->getFilePath(), json_encode($data));
    }
}


<?php

namespace Igniter\Flame\Translation\Middleware;

use Closure;
use Illuminate\Http\Request;

class Localization
{
    /**
     * Handle an incoming request.
     *
     * @param  Request $request
     * @param  Closure $next
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // Don't redirect the console
        // Check for a user defined language and set user language
        if (!app()->runningInConsole()) {
            app('translator.localization')->loadLocale();
        }

        return $next($request);
    }
}


<?php

namespace Neutrino\Database\Migrations;

use Highlight\Highlighter;
use Highlight\Languages\SQL;
use Highlight\Renders\Shell;
use Neutrino\Cli\Output\Decorate;
use Neutrino\Database\Migrations\Prefix\PrefixInterface;
use Neutrino\Database\Migrations\Storage\StorageInterface;
use Neutrino\Database\Schema\Builder;
use Neutrino\Support\Arr;
use Neutrino\Support\Db;
use Neutrino\Support\Str;

/**
 * Class Migrator
 *
 * @package Neutrino\Database\Migrations
 */
class Migrator
{
    /**
     * The migration repository implementation.
     *
     * @var \Neutrino\Database\Migrations\Storage\StorageInterface
     */
    protected $storage;

    /**
     * The migration repository implementation.
     *
     * @var \Neutrino\Database\Migrations\Prefix\PrefixInterface
     */
    protected $prefix;

    /**
     * The notes for the current operation.
     *
     * @var array
     */
    protected $notes = [];

    /**
     * The paths to all of the migration files.
     *
     * @var array
     */
    protected $paths = [];

    /**
     * Migrator constructor.
     *
     * @param \Neutrino\Database\Migrations\Storage\StorageInterface $repository
     * @param \Neutrino\Database\Migrations\Prefix\PrefixInterface   $prefix
     */
    public function __construct(StorageInterface $repository, PrefixInterface $prefix)
    {
        $this->storage = $repository;
        $this->prefix = $prefix;
    }

    /**
     * Run the pending migrations at a given path.
     *
     * @param array|string $paths
     * @param array        $options
     *
     * @return array
     * @throws \Exception
     */
    public function run($paths = [], array $options = [])
    {
        $this->notes = [];

        // Once we grab all of the migration files for the path, we will compare them
        // against the migrations that have already been run for this package then
        // run each of the outstanding migrations against a database connection.
        $files = $this->getMigrationFiles($paths);

        $this->requireFiles($migrations = $this->pendingMigrations(
            $files, $this->storage->getRan()
        ));

        // Once we have all these migrations that are outstanding we are ready to run
        // we will go ahead and run them "up". This will execute each migration as
        // an operation against a database. Then we'll return this list of them.
        $this->runPending($migrations, $options);

        return $migrations;
    }

    /**
     * Get the migration files that have not yet run.
     *
     * @param array $files
     * @param array $ran
     *
     * @return array
     */
    protected function pendingMigrations($files, $ran)
    {
        $pending = [];

        foreach ($files as $file) {
            if (!in_array($this->getMigrationName($file), $ran)) {
                $pending[] = $file;
            }
        }

        return $pending;
    }

    /**
     * Run an array of migrations.
     *
     * @param array $migrations
     * @param array $options
     *
     * @return void
     * @throws \Exception
     */
    public function runPending(array $migrations, array $options = [])
    {
        // First we will just make sure that there are any migrations to run. If there
        // aren't, we will just make a note of it to the developer so they're aware
        // that all of the migrations have been run against this database system.
        if (count($migrations) == 0) {
            $this->note(Decorate::info('Nothing to migrate.'));

            return;
        }

        // Next, we will get the next batch number for the migrations so we can insert
        // correct batch number in the database migrations repository when we store
        // each migration's execution. We will also extract a few of the options.
        $batch = $this->storage->getNextBatchNumber();

        $step = Arr::get($options, 'step', 0);
        $pretend = Arr::get($options, 'pretend', false);

        // Once we have the array of migrations, we will spin through them and run the
        // migrations "up" so the changes are made to the databases. We'll then log
        // that the migration was run so we don't repeat it next time we execute.
        foreach ($migrations as $file) {
            $this->runUp($file, $batch, $pretend);

            if ($step) {
                $batch++;
            }
        }
    }

    /**
     * Run "up" a migration instance.
     *
     * @param string $file
     * @param int    $batch
     * @param bool   $pretend
     *
     * @return void
     * @throws \Exception
     */
    protected function runUp($file, $batch, $pretend = false)
    {
        // First we will resolve a "real" instance of the migration class from this
        // migration file name. Once we have the instances we can run the actual
        // command such as "up" or "down", or we can just simulate the action.
        $migration = $this->resolve(
            $name = $this->getMigrationName($file)
        );

        if ($pretend) {
            $this->pretendToRun($name, $migration, 'up');

            return;
        }

        $this->note(Decorate::notice('Migrating:') . " {$name}");

        $this->runMigration($migration, 'up');

        // Once we have run a migrations class, we will log that it was run in this
        // repository so that we don't try to run it next time we do a migration
        // in the application. A migration repository keeps the migrate order.
        $this->storage->log($name, $batch);

        $this->note(Decorate::info('Migrated:') . " {$name}");
    }

    /**
     * Rollback the last migration operation.
     *
     * @param array|string $paths
     * @param array        $options
     *
     * @return array
     * @throws \Exception
     */
    public function rollback($paths = [], array $options = [])
    {
        $this->notes = [];

        // We want to pull in the last batch of migrations that ran on the previous
        // migration operation. We'll then reverse those migrations and run each
        // of them "down" to reverse the last migration "operation" which ran.
        $migrations = $this->getMigrationsForRollback($options);

        if (count($migrations) === 0) {
            $this->note(Decorate::info('Nothing to rollback.'));

            return [];
        } else {
            return $this->rollbackMigrations($migrations, $paths, $options);
        }
    }

    /**
     * Get the migrations for a rollback operation.
     *
     * @param  array $options
     *
     * @return array
     */
    protected function getMigrationsForRollback(array $options)
    {
        $steps = Arr::get($options, 'step', 0);

        if ($steps > 0) {
            return $this->storage->getMigrations($steps);
        } else {
            return $this->storage->getLast();
        }
    }

    /**
     * Rollback the given migrations.
     *
     * @param array        $migrations
     * @param array|string $paths
     * @param array         $options
     *
     * @return array
     * @throws \Exception
     */
    protected function rollbackMigrations(array $migrations, $paths, array $options)
    {
        $rolledBack = [];

        $pretend = Arr::get($options, 'pretend', false);

        $this->requireFiles($files = $this->getMigrationFiles($paths));

        // Next we will run through all of the migrations and call the "down" method
        // which will reverse each migration in order. This getLast method on the
        // repository already returns these migration's names in reverse order.
        foreach ($migrations as $migration) {
            $migration = (object)$migration;

            if (!$file = Arr::get($files, $migration->migration)) {
                continue;
            }

            $rolledBack[] = $file;

            $this->runDown($file, $migration, $pretend);
        }

        return $rolledBack;
    }

    /**
     * Rolls all of the currently applied migrations back.
     *
     * @param array|string $paths
     * @param array        $options
     *
     * @return array
     * @throws \Exception
     */
    public function reset($paths = [], array $options = [])
    {
        $this->notes = [];

        // Next, we will reverse the migration list so we can run them back in the
        // correct order for resetting this database. This will allow us to get
        // the database back into its "empty" state ready for the migrations.
        $migrations = array_reverse($this->storage->getRan());

        if (count($migrations) === 0) {
            $this->note(Decorate::info('Nothing to rollback.'));

            return [];
        } else {
            return $this->resetMigrations($migrations, $paths, $options);
        }
    }

    /**
     * Reset the given migrations.
     *
     * @param array $migrations
     * @param array $paths
     * @param array $options
     *
     * @return array
     * @throws \Exception
     */
    protected function resetMigrations(array $migrations, array $paths, array $options)
    {
        // Since the getRan method that retrieves the migration name just gives us the
        // migration name, we will format the names into objects with the name as a
        // property on the objects so that we can pass it to the rollback method.
        $migrations = array_map(function ($m) {
            return (object)['migration' => $m];
        }, $migrations);

        return $this->rollbackMigrations($migrations, $paths, $options);
    }

    /**
     * Run "down" a migration instance.
     *
     * @param string $file
     * @param object $migration
     * @param bool   $pretend
     *
     * @return void
     * @throws \Exception
     */
    protected function runDown($file, $migration, $pretend = false)
    {
        // First we will get the file name of the migration so we can resolve out an
        // instance of the migration. Once we get an instance we can either run a
        // pretend execution of the migration or we can run the real migration.
        $instance = $this->resolve(
            $name = $this->getMigrationName($file)
        );

        if ($pretend) {
            $this->pretendToRun($name, $instance, 'down');

            return;
        }

        $this->note(Decorate::notice('Rolling back:') . " {$name}");

        $this->runMigration($instance, 'down');

        // Once we have successfully run the migration "down" we will remove it from
        // the migration repository so it will be considered to have not been run
        // by the application then will be able to fire by any later operation.
        $this->storage->delete($migration->migration);

        $this->note(Decorate::info('Rolled back:') . " {$name}");
    }

    /**
     * Pretend to run the migrations.
     *
     * @param $name
     * @param $instance
     * @param $method
     */
    protected function pretendToRun($name, $instance, $method)
    {
        $this->note(Decorate::info($name) . ': ');

        $queries = Db::pretend(function () use ($instance, $method) {
            $this->runMigration($instance, $method);
        });

        $sql = Highlighter::factory(SQL::class, Shell::class);

        foreach ($queries as $query) {
            $this->note($sql->highlight($query));
        }

        $this->note('');
    }

    /**
     * Run a migration inside a transaction if the database supports it.
     *
     * @param \Neutrino\Database\Migrations\Migration $migration
     * @param string                                  $method
     *
     * @return void
     */
    protected function runMigration($migration, $method)
    {
        if (method_exists($migration, $method)) {
            $migration->{$method}(new Builder());
        }
    }

    /**
     * Resolve a migration instance from a file.
     *
     * @param  string $file
     *
     * @return \Neutrino\Database\Migrations\Migration
     */
    public function resolve($file)
    {
        $class = Str::studly($this->prefix->deletePrefix($file));

        return new $class;
    }

    /**
     * Get all of the migration files in a given path.
     *
     * @param  string|array $paths
     *
     * @return array
     */
    public function getMigrationFiles($paths)
    {
        $paths = array_map(function ($path) {
            return glob($path . '/*_*.php');
        }, (array)$paths);

        $paths = array_filter(Arr::collapse($paths));

        $migrations = [];
        foreach ($paths as $path) {
            $migrations[$this->getMigrationName($path)] = $path;
        }

        ksort($migrations, SORT_REGULAR);

        return $migrations;
    }

    /**
     * Require in all the migration files in a given path.
     *
     * @param  array $files
     *
     * @return void
     */
    public function requireFiles(array $files)
    {
        foreach ($files as $file) {
            require_once $file;
        }
    }

    /**
     * Get the name of the migration.
     *
     * @param  string $path
     *
     * @return string
     */
    public function getMigrationName($path)
    {
        return str_replace('.php', '', basename($path));
    }

    /**
     * Register a custom migration path.
     *
     * @param  string $path
     *
     * @return void
     */
    public function path($path)
    {
        $this->paths = array_unique(array_merge($this->paths, [$path]));
    }

    /**
     * Get all of the custom migration paths.
     *
     * @return array
     */
    public function paths()
    {
        return $this->paths;
    }

    /**
     * Get the migration storage instance.
     *
     * @return \Neutrino\Database\Migrations\Storage\StorageInterface
     */
    public function getStorage()
    {
        return $this->storage;
    }

    /**
     * Determine if the migration repository exists.
     *
     * @return bool
     */
    public function storageExist()
    {
        return $this->storage->storageExist();
    }

    /**
     * Raise a note event for the migrator.
     *
     * @param  string $message
     *
     * @return void
     */
    protected function note($message)
    {
        $this->notes[] = $message;
    }

    /**
     * Get the notes for the last operation.
     *
     * @return array
     */
    public function getNotes()
    {
        return $this->notes;
    }
}


<?php

namespace Neutrino\Foundation\Cli\Tasks;

use Neutrino\Cli\Task;

/**
 * Class ClearCompiledTask
 *
 * @package Neutrino\Foundation\Cli
 */
class ClearCompiledTask extends Task
{
    /**
     * @description Clear compilation.
     */
    public function mainAction()
    {
        self::clearLoader(BASE_PATH . DIRECTORY_SEPARATOR . 'bootstrap/compile/');

        $this->info('The compiled loader has been removed.');
    }

    /**
     * Handle the post-[install|update] Composer event.
     *
     * @return void
     */
    public static function composerClearCompiled()
    {
        self::clearLoader(getcwd() . DIRECTORY_SEPARATOR . 'bootstrap/compile/');
    }

    /**
     * Deleting Compiled Files
     *
     * @param string $compileDir
     */
    private static function clearLoader($compileDir)
    {
        if (file_exists($compileDir . 'loader.php')) {
            @unlink($compileDir . 'loader.php');
        }
        if (file_exists($compileDir . 'compile.php')) {
            @unlink($compileDir . 'compile.php');
        }
    }
}


<?php

namespace Neutrino\Error;

use Neutrino\Support\Arr;
use Phalcon\Logger;

/**
 * Class Helper
 *
 * @package     Neutrino\Error
 */
class Helper
{
    public static function format(Error $error)
    {
        return implode("\n", self::formatLines($error));
    }

    private static function formatLines(Error $error, $pass = 0)
    {
        $pass++;

        $lines[] = self::getErrorType($error->type);
        if ($error->isException) {
            $lines[] = '  Class : ' . get_class($error->exception);
            $lines[] = '  Code : ' . $error->code;
        }

        $lines[] = '  Message : ' . $error->message;

        $lines[] = ' in : ' . str_replace(DIRECTORY_SEPARATOR, '/', $error->file) . '(' . $error->line . ')';

        if ($error->isException) {
            $lines[] = '';

            foreach (self::formatExceptionTrace($error->exception) as $trace) {
                $lines[] = '#' . $trace['id'] . ' ' . $trace['func'];

                $row = str_repeat(' ', strlen($trace['id']) + 2) . 'in : ';
                if (isset($trace['file'])) {
                    $row .= str_replace(DIRECTORY_SEPARATOR, '/', $trace['file']);
                    if (isset($trace['line'])) {
                        $row .= '(' . $trace['line'] . ')';
                    }
                } else {
                    $row .= '[internal function]';
                }

                $lines[] = $row;
            }

            $previous = $error->exception->getPrevious();

            if (!is_null($previous)) {
                $lines[] = '';
                $lines[] = '# Previous exception : ' . $pass;
                $lines[] = '';

                $lines = array_merge($lines, self::formatLines(Error::fromException($previous), $pass));
            }
        }

        return $lines;
    }

    /**
     * @param \Exception $exception
     *
     * @return array
     */
    public static function formatExceptionTrace($exception)
    {
        $traces = [];

        foreach ($exception->getTrace() as $idx => $trace) {
            $_trace = [];

            $_trace['id'] = $idx;

            $_trace['func'] = '';
            if (isset($trace['class'])) {
                $_trace['func'] = $trace['class'] . '->';
            }
            if (isset($trace['function'])) {
                $_trace['func'] .= $trace['function'];
            }

            $args = [];
            if (isset($trace['args'])) {
                $args = self::verboseArgs((array) $trace['args']);
            }
            $_trace['func'] .= '(' . implode(', ', $args) . ')';

            if (isset($trace['file'])) {
                $_trace['file'] = str_replace(DIRECTORY_SEPARATOR, '/', $trace['file']);
                $_trace['where'] = $_trace['file'];

                if (isset($trace['line'])) {
                    $_trace['line'] = $trace['line'];
                    $_trace['where'] .= '(' . $trace['line'] . ')';
                }
            } else {
                $_trace['where'] = '[internal function]';
            }

            $traces[] = $_trace;
        }

        return $traces;
    }

    public static function verboseArgs(array $args)
    {
        $arguments = [];

        foreach ($args as $key => $arg) {
            $arguments[$key] = self::verboseType($arg);
        }

        return $arguments;
    }

    public static function verboseType($value, $lvl = 0)
    {
        switch ($type = gettype($value)) {
            case 'array':
                if (!empty($value) && $lvl === 0) {
                    $found = [];
                    foreach ($value as $item) {
                        $type = gettype($item);
                        if ($type == 'object') {
                            $type = get_class($item);
                        }
                        $found[$type] = true;
                    }

                    $cfound = count($found);
                    $cvalue = count($value);

                    if ($cfound === 1 && !is_scalar($item) && $cvalue < 3
                        || $cfound === 1 && is_scalar($item) && $cvalue < 6
                        || $cfound > 1 && $cvalue < 5) {
                        $str = [];
                        if (Arr::isAssoc($value)) {
                            foreach ($value as $key => $item) {
                                $str[] = var_export($key, true) . " => " . self::verboseType($item, $lvl + 1);
                            }
                        } else {
                            foreach ($value as $item) {
                                $str[] = self::verboseType($item, $lvl + 1);
                            }
                        }

                        return 'array(' . implode(', ', $str) . ')';
                    }

                    if (count($found) === 1) {
                        return 'array.<' . $type . '>[' . count($value) . ']';
                    }

                    return 'array[' . count($value) . ']';
                }

                return 'array';
            case 'object':
                $class = explode('\\', get_class($value));
                return 'object(' . array_pop($class) . ')';
            case 'NULL':
                return 'null';
            case 'unknown type':
                return '?';
            case 'resource':
            case 'resource (closed)':
                return $type;
            case 'string':
                if (constant('BASE_PATH') && $value !== BASE_PATH . '\\') {
                    $value = str_replace(BASE_PATH . '\\', '', $value);
                }
                if (strlen($value) > 20) {
                    return "'" . substr($value, 0, 8) . '...' . substr($value, -8) . '\'[' . strlen($value) . ']';
                }
                return "'" . $value . "'";
            case 'boolean':
            case 'integer':
            case 'double':
            default:
                return var_export($value, true);
        }
    }

    /**
     * Maps error code to a string.
     *
     * @param int|string $code
     *
     * @return string
     */
    public static function getErrorType($code)
    {
        switch ($code) {
            case -1:
                return 'Uncaught exception';
            case E_ERROR:
                return 'E_ERROR';
            case E_WARNING:
                return 'E_WARNING';
            case E_PARSE:
                return 'E_PARSE';
            case E_NOTICE:
                return 'E_NOTICE';
            case E_CORE_ERROR:
                return 'E_CORE_ERROR';
            case E_CORE_WARNING:
                return 'E_CORE_WARNING';
            case E_COMPILE_ERROR:
                return 'E_COMPILE_ERROR';
            case E_COMPILE_WARNING:
                return 'E_COMPILE_WARNING';
            case E_USER_ERROR:
                return 'E_USER_ERROR';
            case E_USER_WARNING:
                return 'E_USER_WARNING';
            case E_USER_NOTICE:
                return 'E_USER_NOTICE';
            case E_STRICT:
                return 'E_STRICT';
            case E_RECOVERABLE_ERROR:
                return 'E_RECOVERABLE_ERROR';
            case E_DEPRECATED:
                return 'E_DEPRECATED';
            case E_USER_DEPRECATED:
                return 'E_USER_DEPRECATED';
        }

        return "(unknown error bit $code)";
    }

    public static function verboseErrorType($code)
    {
        switch ($code) {
            case -1:
                return 'Uncaught exception';
            case E_COMPILE_ERROR:
            case E_CORE_ERROR:
            case E_ERROR:
            case E_PARSE:
            case E_RECOVERABLE_ERROR:
            case E_USER_ERROR:
                return 'Fatal error [' . self::getErrorType($code) . ']';
            case E_WARNING:
            case E_USER_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
                return 'Warning [' . self::getErrorType($code) . ']';
            case E_NOTICE:
            case E_USER_NOTICE:
                return 'Notice [' . self::getErrorType($code) . ']';
            case E_STRICT:
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                return 'Deprecated [' . self::getErrorType($code) . ']';
        }

        return "(unknown error bit $code)";
    }

    /**
     * Maps error code to a log type.
     *
     * @param  integer $code
     *
     * @return integer
     */
    public static function getLogType($code)
    {
        switch ($code) {
            case E_PARSE:
                return Logger::CRITICAL;
            case E_COMPILE_ERROR:
            case E_CORE_ERROR:
            case E_ERROR:
                return Logger::EMERGENCY;
            case -1 : // Exception
            case E_RECOVERABLE_ERROR:
            case E_USER_ERROR:
                return Logger::ERROR;
            case E_WARNING:
            case E_USER_WARNING:
            case E_CORE_WARNING:
            case E_COMPILE_WARNING:
                return Logger::WARNING;
            case E_NOTICE:
            case E_USER_NOTICE:
                return Logger::NOTICE;
            case E_STRICT:
            case E_DEPRECATED:
            case E_USER_DEPRECATED:
                return Logger::INFO;
        }

        return Logger::ERROR;
    }
}


<?php

namespace Neutrino\Config;

use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\NodeVisitorAbstract;

/**
 * Class ReturnTransformer
 *
 * @package Neutrino\Config
 */
class ReturnConverter extends NodeVisitorAbstract
{
    private $name;

    private $variable;

    public function __construct($variable)
    {
        $this->variable = $variable;
    }

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

    /**
     * @param array $nodes
     *
     * @return \PhpParser\Node[]
     * @throws \Exception
     */
    public function afterTraverse(array $nodes)
    {
        $last = $nodes[count($nodes) - 1];

        if (!($last instanceof Return_)) {
            throw new \Exception('Last statement must be the return of config.');
        }

        $exprAssign = new Assign(
            new ArrayDimFetch(
                new Variable($this->variable),
                new String_($this->name)
            ),
            $last->expr
        );

        $nodes[count($nodes) - 1] = $exprAssign;

        return $nodes;
    }
}