private static function extractMultiLines(
        ?string $state,
        array $entry,
        string $line,
        string $key,
        int $i
    ): array {
        $addEntry = static function (array $entry, ?string $state, string $line): array {
            if (! isset($entry[$state])) {
                throw new ParseException([
                    'message' => \sprintf('Parse error! Missing state: [%s].', $state),
                ]);
            }

            // Convert it to array
            if (\is_string($entry[$state])) {
                $entry[$state] = [$entry[$state]];
            }

            $entry[$state][] = self::convertString($line);

            return $entry;
        };

        switch ($state) {
            case 'msgctxt':
            case 'msgid':
            case 'msgid_plural':
                $entry = $addEntry($entry, $state, $line);

                break;
            case 'msgstr':
                $entry['msgstr'][] = self::convertString($line);

                break;

            default:
                if ($state !== null && (\mb_strpos($state, 'msgstr[') !== false)) {
                    $entry = $addEntry($entry, $state, $line);
                } elseif ($key[0] === '#' && $key[1] !== ' ') {
                    throw new ParseException([
                        'message' => \sprintf(
                            'Parse error! Comments must have a space after them on line: [%s].',
                            $i
                        ),
                    ]);
                } else {
                    throw new ParseException([
                        'message' => \sprintf(
                            'Parse error! Unknown key [%s] on line: [%s].',
                            $key,
                            $i
                        ),
                        'line' => $i,
                    ]);
                }
        }

        return $entry;
    }

Export multi-lines from given line.
Throws a exception if state is not found or broken comment is given.

@param null|string $state
@param array       $entry
@param string      $line
@param string      $key
@param int         $i

@throws \Viserio\Component\Contract\Parser\Exception\ParseException

@return array

Export multi - lines from given line . Throws a exception if state is not found or broken comment is given .


private static function extractHeaders(array $headers, array $entries): array
    {
        $currentHeader = null;

        foreach ($headers as $header) {
            $header = \trim($header);
            $header = self::convertString($header);

            if ($header === '') {
                continue;
            }

            if (self::isHeaderDefinition($header)) {
                $header                             = \explode(':', $header, 2);
                $currentHeader                      = \trim($header[0]);
                $entries['headers'][$currentHeader] = \trim($header[1]);
            } else {
                $entries['headers'][$currentHeader] = [$entries['headers'][$currentHeader] ?? '', \trim($header)];
            }
        }

        return $entries;
    }

private static function extractHeaders ( array $ headers , array $ entries ) : array { $ currentHeader = null ; foreach ( $ headers as $ header ) { $ header = \ trim ( $ header ) ; $ header = self :: convertString ( $ header ) ; if ( $ header === '' ) { continue ; } if ( self :: isHeaderDefinition ( $ header ) ) { $ header = \ explode ( ':' , $ header , 2 ) ; $ currentHeader = \ trim ( $ header [ 0 ] ) ; $ entries [ 'headers' ] [ $ currentHeader ] = \ trim ( $ header [ 1 ] ) ; } else { $ entries [ 'headers' ] [ $ currentHeader ] = [ $ entries [ 'headers' ] [ $ currentHeader ] ?? '' , \ trim ( $ header ) ] ; } } return $ entries ; }

Add the headers found to the translations instance.

@param array $headers
@param array $entries

@return array

Add the headers found to the translations instance .


protected function isFile(string $file): bool
    {
        if (! \is_file($file)) {
            throw new InvalidArgumentException(\sprintf('The [%s] file does not exist.', $file));
        }

        return true;
    }

protected
function
isFile
(
string
$
file
)
:
bool
{
if
(
!
\
is_file
(
$
file
)
)
{
throw
new
InvalidArgumentException
(
\
sprintf
(
'The [%s] file does not exist.'
,
$
file
)
)
;
}
return
true
;
}

Check if is file.

@param string $file

@throws \Viserio\Component\Contract\Translation\Exception\InvalidArgumentException

@return bool


private function setError(int $error): void
    {
        if (! \in_array($error, self::ERRORS, true)) {
            throw new InvalidArgumentException('Invalid error status for UploadedFile.');
        }

        $this->error = $error;
    }

Check if error is a int or a array, then set it.

@param int $error

@throws \Viserio\Component\Contract\Http\Exception\InvalidArgumentException

@return void

Check if error is a int or a array then set it .


private function setStreamOrFile($streamOrFile): void
    {
        if (\is_string($streamOrFile)) {
            $this->file = $streamOrFile;

            return;
        }

        if (\is_resource($streamOrFile)) {
            $this->stream = new Stream($streamOrFile);

            return;
        }

        if ($streamOrFile instanceof StreamInterface) {
            $this->stream = $streamOrFile;

            return;
        }

        throw new InvalidArgumentException('Invalid stream or file provided for UploadedFile.');
    }

Set the fill the right variable.

@param mixed $streamOrFile

@throws \Viserio\Component\Contract\Http\Exception\InvalidArgumentException

@return void


private function validateActive(): void
    {
        if ($this->isOk() === false) {
            throw new RuntimeException(\sprintf(
                'Cannot retrieve stream due to upload error: %s',
                self::$errorMessages[$this->error]
            ));
        }

        if ($this->isMoved()) {
            throw new RuntimeException('Cannot retrieve stream after it has already been moved.');
        }
    }

Validate retrieve stream.

@throws \Viserio\Component\Contract\Http\Exception\RuntimeException if is moved or not ok

@return void


public function mock(...$args): MockInterface
    {
        $id = \array_shift($args);

        if (! $this->has($id)) {
            throw new InvalidArgumentException(\sprintf('Cannot mock a non-existent service: [%s]', $id));
        }

        $mock = 'mock::' . $id;

        if (! isset($this->mockedServices[$mock])) {
            $this->mockedServices[$mock] = \call_user_func_array([Mockery::class, 'mock'], $args);
        }

        return $this->mockedServices[$mock];
    }

Takes an id of the service as the first argument.
Any other arguments are passed to the Mockery factory.

@param array<int, mixed> $args

@throws \Viserio\Component\Contract\Container\Exception\InvalidArgumentException

@return \Mockery\MockInterface

Takes an id of the service as the first argument . Any other arguments are passed to the Mockery factory .


public static function parse(string $expression): array
    {
        \preg_match_all('/^\S*|(\[\s*(.*?)\]|[[:alnum:]_-]+\=\*|[[:alnum:]_-]+\?|[[:alnum:]_-]+|-+[[:alnum:]_\-=*]+)/', $expression, $matches);

        if (\trim($expression) === '') {
            throw new InvalidCommandExpression('The expression was empty.');
        }

        $tokens    = \array_values(\array_filter(\array_map('trim', $matches[0])));
        $name      = \array_shift($tokens);
        $arguments = [];
        $options   = [];

        foreach ($tokens as $token) {
            if (self::startsWith($token, '--')) {
                throw new InvalidCommandExpression('An option must be enclosed by brackets: [--option].');
            }

            if (self::isOption($token)) {
                $options[] = self::parseOption($token);
            } else {
                $arguments[] = self::parseArgument($token);
            }
        }

        return [
            'name'      => $name,
            'arguments' => $arguments,
            'options'   => $options,
        ];
    }

Parse given command string.

@param string $expression

@throws \Viserio\Component\Contract\Console\Exception\InvalidCommandExpression

@return array


private static function parseArgument(string $token): InputArgument
    {
        [$token, $description] = static::extractDescription($token);

        switch (true) {
            case self::endsWith($token, '=*]'):
                return new InputArgument(\trim($token, '[=*]'), InputArgument::IS_ARRAY, $description);
            case self::endsWith($token, '=*'):
                return new InputArgument(\trim($token, '=*'), InputArgument::IS_ARRAY | InputArgument::REQUIRED, $description);
            case \preg_match('/(.*)\?$/', $token, $matches):
                return new InputArgument($matches[1], InputArgument::OPTIONAL, $description);
            case \preg_match('/\[(.+)\?\]/', $token, $matches):
                return new InputArgument($matches[1], InputArgument::OPTIONAL, $description);
            case \preg_match('/\[(.+)\=\*(.+)\]/', $token, $matches):
                return new InputArgument($matches[1], InputArgument::IS_ARRAY, $description, \preg_split('/,\s?/', $matches[2]));
            case \preg_match('/\[(.+)\=(.+)\]/', $token, $matches):
                return new InputArgument($matches[1], InputArgument::OPTIONAL, $description, $matches[2]);
            case self::startsWith($token, '[') && self::endsWith($token, ']'):
                return new InputArgument(\trim($token, '[]'), InputArgument::OPTIONAL, $description);

            default:
                return new InputArgument($token, InputArgument::REQUIRED, $description);
        }
    }

private static function parseArgument ( string $ token ) : InputArgument { [ $ token , $ description ] = static :: extractDescription ( $ token ) ; switch ( true ) { case self :: endsWith ( $ token , '=*]' ) : return new InputArgument ( \ trim ( $ token , '[=*]' ) , InputArgument :: IS_ARRAY , $ description ) ; case self :: endsWith ( $ token , '=*' ) : return new InputArgument ( \ trim ( $ token , '=*' ) , InputArgument :: IS_ARRAY | InputArgument :: REQUIRED , $ description ) ; case \ preg_match ( '/(.*)\?$/' , $ token , $ matches ) : return new InputArgument ( $ matches [ 1 ] , InputArgument :: OPTIONAL , $ description ) ; case \ preg_match ( '/\[(.+)\?\]/' , $ token , $ matches ) : return new InputArgument ( $ matches [ 1 ] , InputArgument :: OPTIONAL , $ description ) ; case \ preg_match ( '/\[(.+)\=\*(.+)\]/' , $ token , $ matches ) : return new InputArgument ( $ matches [ 1 ] , InputArgument :: IS_ARRAY , $ description , \ preg_split ( '/,\s?/' , $ matches [ 2 ] ) ) ; case \ preg_match ( '/\[(.+)\=(.+)\]/' , $ token , $ matches ) : return new InputArgument ( $ matches [ 1 ] , InputArgument :: OPTIONAL , $ description , $ matches [ 2 ] ) ; case self :: startsWith ( $ token , '[' ) && self :: endsWith ( $ token , ']' ) : return new InputArgument ( \ trim ( $ token , '[]' ) , InputArgument :: OPTIONAL , $ description ) ; default : return new InputArgument ( $ token , InputArgument :: REQUIRED , $ description ) ; } }

Parse arguments.

@param string $token

@throws \Symfony\Component\Console\Exception\InvalidArgumentException

@return \Viserio\Component\Console\Input\InputArgument


private static function parseOption(string $token): InputOption
    {
        [$token, $description] = static::extractDescription(\trim($token, '[]'));

        // Shortcut [-y|--yell]
        if (\mb_strpos($token, '|') !== false) {
            [$shortcut, $token] = \explode('|', $token, 2);
            $shortcut           = \ltrim($shortcut, '-');
        } else {
            $shortcut = null;
        }

        $name    = \ltrim($token, '-');
        $default = null;

        switch (true) {
            case self::endsWith($token, '=*'):
                return new InputOption(\rtrim($name, '=*'), $shortcut, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, $description);
            case self::endsWith($token, '='):
                return new InputOption(\rtrim($name, '='), $shortcut, InputOption::VALUE_REQUIRED, $description);
            case \preg_match('/(.+)\=\*(.+)/', $token, $matches):
                return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, $description, \preg_split('/,\s?/', $matches[2]));
            case \preg_match('/(.+)\=(.+)/', $token, $matches):
                return new InputOption($matches[1], $shortcut, InputOption::VALUE_OPTIONAL, $description, $matches[2]);

            default:
                return new InputOption($token, $shortcut, InputOption::VALUE_NONE, $description);
        }
    }

private
static
function
parseOption
(
string
$
token
)
:
InputOption
{
[
$
token
,
$
description
]
=
static
::
extractDescription
(
\
trim
(
$
token
,
'[]'
)
)
;
// Shortcut [-y|--yell]
if
(
\
mb_strpos
(
$
token
,
'|'
)
!==
false
)
{
[
$
shortcut
,
$
token
]
=
\
explode
(
'|'
,
$
token
,
2
)
;
$
shortcut
=
\
ltrim
(
$
shortcut
,
'-'
)
;
}
else
{
$
shortcut
=
;
}
$
name
=
\
ltrim
(
$
token
,
'-'
)
;
$
default
=
;
switch
(
true
)
{
case
self
::
endsWith
(
$
token
,
'=*'
)
:
return
new
InputOption
(
\
rtrim
(
$
name
,
'=*'
)
,
$
shortcut
,
InputOption
::
VALUE_REQUIRED
|
InputOption
::
VALUE_IS_ARRAY
,
$
description
)
;
case
self
::
endsWith
(
$
token
,
'='
)
:
return
new
InputOption
(
\
rtrim
(
$
name
,
'='
)
,
$
shortcut
,
InputOption
::
VALUE_REQUIRED
,
$
description
)
;
case
\
preg_match
(
'/(.+)\=\*(.+)/'
,
$
token
,
$
matches
)
:
return
new
InputOption
(
$
matches
[
1
]
,
$
shortcut
,
InputOption
::
VALUE_OPTIONAL
|
InputOption
::
VALUE_IS_ARRAY
,
$
description
,
\
preg_split
(
'/,\s?/'
,
$
matches
[
2
]
)
)
;
case
\
preg_match
(
'/(.+)\=(.+)/'
,
$
token
,
$
matches
)
:
return
new
InputOption
(
$
matches
[
1
]
,
$
shortcut
,
InputOption
::
VALUE_OPTIONAL
,
$
description
,
$
matches
[
2
]
)
;
default
:
return
new
InputOption
(
$
token
,
$
shortcut
,
InputOption
::
VALUE_NONE
,
$
description
)
;
}
}

Parse options.

@param string $token

@throws \Symfony\Component\Console\Exception\InvalidArgumentException

@return \Viserio\Component\Console\Input\InputOption


private static function extractDescription(string $token): array
    {
        \preg_match('/(.*)\s:(\s+.*(?<!]))(.*)/', \trim($token), $parts);

        return \count($parts) === 4 ? [$parts[1] . $parts[3], \trim($parts[2])] : [$token, ''];
    }

private static function extractDescription ( string $ token ) : array { \ preg_match ( '/(.*)\s:(\s+.*(?<!]))(.*)/' , \ trim ( $ token ) , $ parts ) ; return \ count ( $ parts ) === 4 ? [ $ parts [ 1 ] . $ parts [ 3 ] , \ trim ( $ parts [ 2 ] ) ] : [ $ token , '' ] ; }

Parse the token into its token and description segments.

@param string $token

@return array

Parse the token into its token and description segments .


protected function validateName(string $name): void
    {
        if ($name === '') {
            throw new InvalidArgumentException('The name cannot be empty.');
        }

        // Name attribute is a token as per spec in RFC 2616
        if (\preg_match('/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5b-\x5d\x7b\x7d\x7f]/', $name)) {
            throw new InvalidArgumentException(\sprintf(
                'Cookie name [%s] must not contain invalid characters: ASCII Control characters (0-31;127), space, tab and the following characters: ()<>@,;:\"/[]?={}',
                $name
            ));
        }
    }

Validates the name attribute.

@param string $name

@throws \Viserio\Component\Contract\Cookie\Exception\InvalidArgumentException

@see http://tools.ietf.org/search/rfc2616#section-2.2

@return void


protected function validateValue(?string $value = null): void
    {
        if ($value !== null && \preg_match('/[^\x21\x23-\x2B\x2D-\x3A\x3C-\x5B\x5D-\x7E]/', $value)) {
            throw new InvalidArgumentException(
                \sprintf(
                    'The cookie value [%s] contains invalid characters.',
                    $value
                )
            );
        }
    }

Validates a value.

@param null|string $value

@throws \Viserio\Component\Contract\Cookie\Exception\InvalidArgumentException

@see http://tools.ietf.org/html/rfc6265#section-4.1.1

@return void


public function set(string $key, $value)
    {
        if ($this->left) {
            throw new \LogicException('Left scope is not mutable.');
        }

        $this->data[$key] = $value;

        return $this;
    }

public
function
set
(
string
$
key
,
$
value
)
{
if
(
$
this
->
left
)
{
throw
new
\
LogicException
(
'Left scope is not mutable.'
)
;
}
$
this
->
data
[
$
key
]
=
$
value
;
return
$
this
;
}

Stores data into current scope.

@param string $key
@param mixed  $value

@throws \LogicException

@return $this


protected function getToAddresses(Swift_Mime_SimpleMessage $message): array
    {
        $to = [];

        $getTo = $message->getTo();

        if (\is_array($getTo)) {
            $to = \array_merge($to, \array_keys($getTo));
        }

        $cc = $message->getCc();

        if (\is_array($cc)) {
            $to = \array_merge($to, \array_keys($cc));
        }

        $bcc = $message->getBcc();

        if (\is_array($bcc)) {
            $to = \array_merge($to, \array_keys($bcc));
        }

        return $to;
    }

protected function getToAddresses ( Swift_Mime_SimpleMessage $ message ) : array { $ to = [ ] ; $ getTo = $ message -> getTo ( ) ; if ( \ is_array ( $ getTo ) ) { $ to = \ array_merge ( $ to , \ array_keys ( $ getTo ) ) ; } $ cc = $ message -> getCc ( ) ; if ( \ is_array ( $ cc ) ) { $ to = \ array_merge ( $ to , \ array_keys ( $ cc ) ) ; } $ bcc = $ message -> getBcc ( ) ; if ( \ is_array ( $ bcc ) ) { $ to = \ array_merge ( $ to , \ array_keys ( $ bcc ) ) ; } return $ to ; }

Get all the addresses this email should be sent to,
including "to", "cc" and "bcc" addresses.

@param \Swift_Mime_SimpleMessage $message

@return array

Get all the addresses this email should be sent to including to cc and bcc addresses .


protected function createMongodbDriver(array $config): MongoDBCachePool
    {
        if (isset($config['username'], $config['password'])) {
            $dns = \sprintf(
                'mongodb://%s:%s@%s:%s',
                $config['username'],
                $config['password'],
                $config['server'],
                $config['port']
            );
        } else {
            $dns = \sprintf('mongodb://%s:%s', $config['server'], $config['port']);
        }

        $collection = MongoDBCachePool::createCollection(
            new MongoDBManager($dns),
            $config['database'],
            $config['prefix']
        );

        return new MongoDBCachePool($collection);
    }

protected function createMongodbDriver ( array $ config ) : MongoDBCachePool { if ( isset ( $ config [ 'username' ] , $ config [ 'password' ] ) ) { $ dns = \ sprintf ( 'mongodb://%s:%s@%s:%s' , $ config [ 'username' ] , $ config [ 'password' ] , $ config [ 'server' ] , $ config [ 'port' ] ) ; } else { $ dns = \ sprintf ( 'mongodb://%s:%s' , $ config [ 'server' ] , $ config [ 'port' ] ) ; } $ collection = MongoDBCachePool :: createCollection ( new MongoDBManager ( $ dns ) , $ config [ 'database' ] , $ config [ 'prefix' ] ) ; return new MongoDBCachePool ( $ collection ) ; }

Create an instance of the MongoDB cache driver.

@param array $config

@throws \MongoDB\Driver\Exception\RuntimeException
@throws \MongoDB\Driver\Exception\InvalidArgumentException

@return \Cache\Adapter\MongoDB\MongoDBCachePool

@codeCoverageIgnore

Create an instance of the MongoDB cache driver .


protected function createRedisDriver(array $config): RedisCachePool
    {
        $client = new Redis();
        $client->connect($config['host'], $config['port']);

        return new RedisCachePool($client);
    }

protected function createRedisDriver ( array $ config ) : RedisCachePool { $ client = new Redis ( ) ; $ client -> connect ( $ config [ 'host' ] , $ config [ 'port' ] ) ; return new RedisCachePool ( $ client ) ; }

Create an instance of the Redis cache driver.

@param array $config

@return \Cache\Adapter\Redis\RedisCachePool

@codeCoverageIgnore

Create an instance of the Redis cache driver .


protected function createPredisDriver(array $config): PredisCachePool
    {
        $client = new PredisClient(\sprintf('tcp:/%s:%s', $config['server'], $config['port']));

        return new PredisCachePool($client);
    }

protected function createPredisDriver ( array $ config ) : PredisCachePool { $ client = new PredisClient ( \ sprintf ( 'tcp:/%s:%s' , $ config [ 'server' ] , $ config [ 'port' ] ) ) ; return new PredisCachePool ( $ client ) ; }

Create an instance of the Predis cache driver.

@param array $config

@return \Cache\Adapter\Predis\PredisCachePool

@codeCoverageIgnore

Create an instance of the Predis cache driver .


protected function createFilesystemDriver(array $config): FilesystemCachePool
    {
        $adapter = $this->container->get($config['connection']);

        return new FilesystemCachePool(new Flysystem($adapter));
    }

protected function createFilesystemDriver ( array $ config ) : FilesystemCachePool { $ adapter = $ this -> container -> get ( $ config [ 'connection' ] ) ; return new FilesystemCachePool ( new Flysystem ( $ adapter ) ) ; }

Create an instance of the Flysystem cache driver.

@param array $config

@return \Cache\Adapter\Filesystem\FilesystemCachePool

Create an instance of the Flysystem cache driver .


protected function createMemcachedDriver(array $config): MemcachedCachePool
    {
        $client = new Memcached();
        $client->addServer($config['host'], $config['port']);

        return new MemcachedCachePool($client);
    }

protected function createMemcachedDriver ( array $ config ) : MemcachedCachePool { $ client = new Memcached ( ) ; $ client -> addServer ( $ config [ 'host' ] , $ config [ 'port' ] ) ; return new MemcachedCachePool ( $ client ) ; }

Create an instance of the Memcached cache driver.

@param array $config

@return \Cache\Adapter\Memcached\MemcachedCachePool

@codeCoverageIgnore

Create an instance of the Memcached cache driver .


protected function createMemcacheDriver(array $config): MemcacheCachePool
    {
        $client = new Memcache();
        $client->addServer($config['host'], $config['port']);

        return new MemcacheCachePool($client);
    }

protected function createMemcacheDriver ( array $ config ) : MemcacheCachePool { $ client = new Memcache ( ) ; $ client -> addServer ( $ config [ 'host' ] , $ config [ 'port' ] ) ; return new MemcacheCachePool ( $ client ) ; }

Create an instance of the Memcache cache driver.

@param array $config

@return \Cache\Adapter\Memcache\MemcacheCachePool

@codeCoverageIgnore

Create an instance of the Memcache cache driver .


public function getCollector(string $name): DataCollectorContract
    {
        if (! isset($this->collectors[$name])) {
            throw new CollectorNotFoundException(\sprintf('Collector [%s] not found.', $name));
        }

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

public
function
getCollector
(
string
$
name
)
:
DataCollectorContract
{
if
(
!
isset
(
$
this
->
collectors
[
$
name
]
)
)
{
throw
new
CollectorNotFoundException
(
\
sprintf
(
'Collector [%s] not found.'
,
$
name
)
)
;
}
return
$
this
->
collectors
[
$
name
]
;
}

Gets a Collector by name.

@param string $name A collector name

@throws \Viserio\Component\Contract\Profiler\Exception\CollectorNotFoundException if the collector does not exist

@return \Viserio\Component\Contract\Profiler\DataCollector


public function compile(array $routes): string
    {
        $routeTree = $this->treeOptimizer->optimize(
            $this->treeBuilder->build($routes)
        );

        $code         = new PHPCodeCollection();
        $code->indent = 1;

        $this->compileRouteTree($code, $routeTree);

        $rootRouteCode         = new PHPCodeCollection();
        $rootRouteCode->indent = 2;

        $this->compileNotFound($rootRouteCode);

        return $this->createRouterClassTemplate(\substr($rootRouteCode->code, 0, -\strlen(\PHP_EOL)), $code->code);
    }

public function compile ( array $ routes ) : string { $ routeTree = $ this -> treeOptimizer -> optimize ( $ this -> treeBuilder -> build ( $ routes ) ) ; $ code = new PHPCodeCollection ( ) ; $ code -> indent = 1 ; $ this -> compileRouteTree ( $ code , $ routeTree ) ; $ rootRouteCode = new PHPCodeCollection ( ) ; $ rootRouteCode -> indent = 2 ; $ this -> compileNotFound ( $ rootRouteCode ) ; return $ this -> createRouterClassTemplate ( \ substr ( $ rootRouteCode -> code , 0 , - \ strlen ( \ PHP_EOL ) ) , $ code -> code ) ; }

Complie all added routes to a router handler.

@param array $routes

@return string

Complie all added routes to a router handler .


private function createRouterClassTemplate(string $rootRoute, string $body): string
    {
        $template = <<<'PHP'
<?php
return function ($method, $uri) {
    if ($uri === '') {
{root_route}
    } elseif ($uri[0] !== '/') {
        throw new \RuntimeException("Cannot match route: non-empty uri must be prefixed with '/', '{$uri}' given");
    }

    $segments = \explode('/', \substr($uri, 1));
{body}
};
PHP;

        return \strtr($template, ['{root_route}' => $rootRoute, '{body}' => $body]);
    }

Creating a template for the router class.

@param string $rootRoute
@param string $body

@return string

Creating a template for the router class .


private function compileRouteTree(PHPCodeCollection $code, array $routeTree): void
    {
        $code->appendLine('switch (count($segments)) {');

        $code->indent++;

        foreach ($routeTree[1] as $segmentDepth => $nodes) {
            $code->appendLine('case ' . $segmentDepth . ':');

            $code->indent++;

            $segmentVariables = [];

            for ($i = 0; $i < $segmentDepth; $i++) {
                $segmentVariables[$i] = '$s' . $i;
            }

            $code->appendLine('[' . \implode(', ', $segmentVariables) . '] = $segments;');

            $this->compileSegmentNodes($code, $nodes, $segmentVariables);
            $this->compileDisallowedHttpMethodOrNotFound($code);

            $code->appendLine('break;');

            $code->indent--;

            $code->appendLine();
        }

        $code->appendLine('default:');

        $code->indent++;

        $this->compileNotFound($code);

        $code->indent--;
        $code->indent--;

        $code->append('}');
    }

private
function
compileRouteTree
(
PHPCodeCollection
$
code
,
array
$
routeTree
)
:
void
{
$
code
->
appendLine
(
'switch (count($segments)) {'
)
;
$
code
->
indent
++
;
foreach
(
$
routeTree
[
1
]
as
$
segmentDepth
=>
$
nodes
)
{
$
code
->
appendLine
(
'case '
.
$
segmentDepth
.
':'
)
;
$
code
->
indent
++
;
$
segmentVariables
=
[
]
;
for
(
$
i
=
0
;
$
i
<
$
segmentDepth
;
$
i
++
)
{
$
segmentVariables
[
$
i
]
=
'$s'
.
$
i
;
}
$
code
->
appendLine
(
'['
.
\
implode
(
', '
,
$
segmentVariables
)
.
'] = $segments;'
)
;
$
this
->
compileSegmentNodes
(
$
code
,
$
nodes
,
$
segmentVariables
)
;
$
this
->
compileDisallowedHttpMethodOrNotFound
(
$
code
)
;
$
code
->
appendLine
(
'break;'
)
;
$
code
->
indent
;
$
code
->
appendLine
(
)
;
}
$
code
->
appendLine
(
'default:'
)
;
$
code
->
indent
++
;
$
this
->
compileNotFound
(
$
code
)
;
$
code
->
indent
;
$
code
->
indent
;
$
code
->
append
(
'}'
)
;
}

Compile the counter for the segments check.

@param \Viserio\Component\Routing\TreeGenerator\PHPCodeCollection $code
@param array                                                      $routeTree

Compile the counter for the segments check .


private function compiledRouteHttpMethodMatch(
        PHPCodeCollection $code,
        MatchedRouteDataMap $routeDataMap,
        array $parameters
    ): void {
        $code->appendLine('switch ($method) {');

        $code->indent++;

        foreach ($routeDataMap->getHttpMethodRouteDataMap() as $item) {
            [$httpMethods, $routeData] = $item;

            foreach ($httpMethods as $httpMethod) {
                $code->appendLine('case \'' . $httpMethod . '\':');
            }

            $code->indent++;

            $this->compileFoundRoute($code, $routeData, $parameters);

            $code->indent--;
        }

        $code->appendLine('default:');

        $code->indent++;

        foreach ($routeDataMap->allowedHttpMethods() as $method) {
            $code->appendLine('$allowedHttpMethods[] = \'' . $method . '\';');
        }

        $code->appendLine('break;');

        $code->indent--;
        $code->indent--;

        $code->appendLine('}');
    }

private
function
compiledRouteHttpMethodMatch
(
PHPCodeCollection
$
code
,
MatchedRouteDataMap
$
routeDataMap
,
array
$
parameters
)
:
void
{
$
code
->
appendLine
(
'switch ($method) {'
)
;
$
code
->
indent
++
;
foreach
(
$
routeDataMap
->
getHttpMethodRouteDataMap
(
)
as
$
item
)
{
[
$
httpMethods
,
$
routeData
]
=
$
item
;
foreach
(
$
httpMethods
as
$
httpMethod
)
{
$
code
->
appendLine
(
'case \''
.
$
httpMethod
.
'\':'
)
;
}
$
code
->
indent
++
;
$
this
->
compileFoundRoute
(
$
code
,
$
routeData
,
$
parameters
)
;
$
code
->
indent
;
}
$
code
->
appendLine
(
'default:'
)
;
$
code
->
indent
++
;
foreach
(
$
routeDataMap
->
allowedHttpMethods
(
)
as
$
method
)
{
$
code
->
appendLine
(
'$allowedHttpMethods[] = \''
.
$
method
.
'\';'
)
;
}
$
code
->
appendLine
(
'break;'
)
;
$
code
->
indent
;
$
code
->
indent
;
$
code
->
appendLine
(
'}'
)
;
}

Compile the route http method match switch.

@param \Viserio\Component\Routing\TreeGenerator\PHPCodeCollection   $code
@param \Viserio\Component\Routing\TreeGenerator\MatchedRouteDataMap $routeDataMap
@param array                                                        $parameters

Compile the route http method match switch .


private function compileDisallowedHttpMethodOrNotFound(PHPCodeCollection $code): void
    {
        $code->appendLine(
            'return ' .
            'isset($allowedHttpMethods) '
            . '? '
            . '['
            . DispatcherContract::HTTP_METHOD_NOT_ALLOWED
            . ', $allowedHttpMethods] '
            . ': '
            . '['
            . DispatcherContract::NOT_FOUND
            . '];'
        );
    }

private
function
compileDisallowedHttpMethodOrNotFound
(
PHPCodeCollection
$
code
)
:
void
{
$
code
->
appendLine
(
'return '
.
'isset($allowedHttpMethods) '
.
'? '
.
'['
.
DispatcherContract
::
HTTP_METHOD_NOT_ALLOWED
.
', $allowedHttpMethods] '
.
': '
.
'['
.
DispatcherContract
::
NOT_FOUND
.
'];'
)
;
}

Compile disallowed http method or not found data check.

@param \Viserio\Component\Routing\TreeGenerator\PHPCodeCollection $code

Compile disallowed http method or not found data check .


private function compileFoundRoute(PHPCodeCollection $code, array $foundRoute, array $parameterExpressions): void
    {
        $parameters = '[';

        foreach ($foundRoute[0] as $index => $parameterName) {
            $parameters .= '\'' . $parameterName . '\' => ' . $parameterExpressions[$index] . ', ';
        }

        if (\strlen($parameters) > 2) {
            $parameters = \substr($parameters, 0, -2);
        }

        $parameters .= ']';

        $code->appendLine(
            'return ['
            . DispatcherContract::FOUND
            . ', '
            . '\'' . $foundRoute[1] . '\''
            . ', '
            . $parameters
            . '];'
        );
    }

private
function
compileFoundRoute
(
PHPCodeCollection
$
code
,
array
$
foundRoute
,
array
$
parameterExpressions
)
:
void
{
$
parameters
=
'['
;
foreach
(
$
foundRoute
[
0
]
as
$
index
=>
$
parameterName
)
{
$
parameters
.=
'\''
.
$
parameterName
.
'\' => '
.
$
parameterExpressions
[
$
index
]
.
', '
;
}
if
(
\
strlen
(
$
parameters
)
>
2
)
{
$
parameters
=
\
substr
(
$
parameters
,
0
,
2
)
;
}
$
parameters
.=
']'
;
$
code
->
appendLine
(
'return ['
.
DispatcherContract
::
FOUND
.
', '
.
'\''
.
$
foundRoute
[
1
]
.
'\''
.
', '
.
$
parameters
.
'];'
)
;
}

Compile the found route data.

@param \Viserio\Component\Routing\TreeGenerator\PHPCodeCollection $code
@param array                                                      $foundRoute
@param array                                                      $parameterExpressions


private function getDebugLogger(): ?DebugProcessor
    {
        foreach ($this->logger->getProcessors() as $processor) {
            if ($processor instanceof DebugProcessor) {
                return $processor;
            }
        }

        return null;
    }

private function getDebugLogger ( ) : ? DebugProcessor { foreach ( $ this -> logger -> getProcessors ( ) as $ processor ) { if ( $ processor instanceof DebugProcessor ) { return $ processor ; } } return null ; }

Returns a DebugProcessor instance if one is registered with this logger.

@return null|\Viserio\Bridge\Monolog\Processor\DebugProcessor

Returns a DebugProcessor instance if one is registered with this logger .


private function getComputedErrorsCount(): array
    {
        $errorCount = 0;

        if ($logger = $this->getDebugLogger()) {
            $errorCount = $logger->countErrors();
        }

        $count = [
            'error_count'       => $errorCount,
            'deprecation_count' => 0,
            'warning_count'     => 0,
            'scream_count'      => 0,
            'priorities'        => [],
        ];

        foreach ($this->getLogs() as $log) {
            if (isset($count['priorities'][$log['priority']])) {
                $count['priorities'][$log['priority']]['count']++;
            } else {
                $count['priorities'][$log['priority']] = [
                    'count' => 1,
                    'name'  => $log['priorityName'],
                ];
            }

            if ('WARNING' === $log['priorityName']) {
                $count['warning_count']++;
            }

            if ($this->isSilencedOrDeprecationErrorLog($log)) {
                if ($log['context']['exception'] instanceof SilencedErrorContext) {
                    $count['scream_count']++;
                } else {
                    $count['deprecation_count']++;
                }
            }
        }

        \ksort($count['priorities']);

        return $count;
    }

private function getComputedErrorsCount ( ) : array { $ errorCount = 0 ; if ( $ logger = $ this -> getDebugLogger ( ) ) { $ errorCount = $ logger -> countErrors ( ) ; } $ count = [ 'error_count' => $ errorCount , 'deprecation_count' => 0 , 'warning_count' => 0 , 'scream_count' => 0 , 'priorities' => [ ] , ] ; foreach ( $ this -> getLogs ( ) as $ log ) { if ( isset ( $ count [ 'priorities' ] [ $ log [ 'priority' ] ] ) ) { $ count [ 'priorities' ] [ $ log [ 'priority' ] ] [ 'count' ] ++ ; } else { $ count [ 'priorities' ] [ $ log [ 'priority' ] ] = [ 'count' => 1 , 'name' => $ log [ 'priorityName' ] , ] ; } if ( 'WARNING' === $ log [ 'priorityName' ] ) { $ count [ 'warning_count' ] ++ ; } if ( $ this -> isSilencedOrDeprecationErrorLog ( $ log ) ) { if ( $ log [ 'context' ] [ 'exception' ] instanceof SilencedErrorContext ) { $ count [ 'scream_count' ] ++ ; } else { $ count [ 'deprecation_count' ] ++ ; } } } \ ksort ( $ count [ 'priorities' ] ) ; return $ count ; }

Get computed log error levels.

@return array


private function groupLogLevels(): array
    {
        $deprecationLogs  = [];
        $debugLogs        = [];
        $infoAndErrorLogs = [];
        $silencedLogs     = [];

        $formatLog = function ($log) {
            return[
                $log['priorityName'] . '
' . '
' . \date('H:i:s', $log['timestamp']) . '
',
                $log['channel'],
                $log['message'] . '
' . (\count($log['context']) !== 0 ? $this->cloneVar($log['context']) : ''),
            ];
        };

        foreach ((array) $this->data['logs'] as $log) {
            if (isset($log['priority'])) {
                if (\in_array($log['priority'], [Logger::ERROR, Logger::INFO], true)) {
                    $infoAndErrorLogs[] = $formatLog($log);
                } elseif ($log['priority'] === Logger::DEBUG) {
                    $debugLogs[] = $formatLog($log);
                }
            } elseif ($this->isSilencedOrDeprecationErrorLog($log)) {
                if (isset($log['context']) && $log['context']['exception'] instanceof SilencedErrorContext) {
                    $silencedLogs[] = $formatLog($log);
                } else {
                    $deprecationLogs[] = $formatLog($log);
                }
            }
        }

        return [
            'deprecation' => $deprecationLogs,
            'debug'       => $debugLogs,
            'info_error'  => $infoAndErrorLogs,
            'silenced'    => $silencedLogs,
        ];
    }

private
function
groupLogLevels
(
)
:
array
{
$
deprecationLogs
=
[
]
;
$
debugLogs
=
[
]
;
$
infoAndErrorLogs
=
[
]
;
$
silencedLogs
=
[
]
;
$
formatLog
=
function
(
$
log
)
{
return
[
$
log
[
'priorityName'
]
.
'
'
.
'
'
.
\
date
(
'H:i:s'
,
$
log
[
'timestamp'
]
)
.
'
'
,
$
log
[
'channel'
]
,
$
log
[
'message'
]
.
'
'
.
(
\
count
(
$
log
[
'context'
]
)
!==
0
$
this
->
cloneVar
(
$
log
[
'context'
]
)
:
''
)
,
]
;
}
;
foreach
(
(
array
)
$
this
->
data
[
'logs'
]
as
$
log
)
{
if
(
isset
(
$
log
[
'priority'
]
)
)
{
if
(
\
in_array
(
$
log
[
'priority'
]
,
[
Logger
::
ERROR
,
Logger
::
INFO
]
,
true
)
)
{
$
infoAndErrorLogs
[
]
=
$
formatLog
(
$
log
)
;
}
elseif
(
$
log
[
'priority'
]
===
Logger
::
DEBUG
)
{
$
debugLogs
[
]
=
$
formatLog
(
$
log
)
;
}
}
elseif
(
$
this
->
isSilencedOrDeprecationErrorLog
(
$
log
)
)
{
if
(
isset
(
$
log
[
'context'
]
)
&&
$
log
[
'context'
]
[
'exception'
]
instanceof
SilencedErrorContext
)
{
$
silencedLogs
[
]
=
$
formatLog
(
$
log
)
;
}
else
{
$
deprecationLogs
[
]
=
$
formatLog
(
$
log
)
;
}
}
}
return
[
'deprecation'
=>
$
deprecationLogs
,
'debug'
=>
$
debugLogs
,
'info_error'
=>
$
infoAndErrorLogs
,
'silenced'
=>
$
silencedLogs
,
]
;
}

Group log level together.

@return array


public function getListener()
    {
        if ($this->listener === null && $this->provider !== null) {
            $this->listener = $this->provider;
            $this->provider = null;
        }

        return $this->listener;
    }

public function getListener ( ) { if ( $ this -> listener === null && $ this -> provider !== null ) { $ this -> listener = $ this -> provider ; $ this -> provider = null ; } return $ this -> listener ; }


public function bind(EventManagerContract $dispatcher, string $eventName): void
    {
        if (isset($this->events[$eventName])) {
            return;
        }

        $dispatcher->attach($eventName, $this->getListener(), $this->priority);
        $this->events[$eventName] = true;
    }

public function bind ( EventManagerContract $ dispatcher , string $ eventName ) : void { if ( isset ( $ this -> events [ $ eventName ] ) ) { return ; } $ dispatcher -> attach ( $ eventName , $ this -> getListener ( ) , $ this -> priority ) ; $ this -> events [ $ eventName ] = true ; }

Adds this pattern's listener to an event.

@param \Viserio\Component\Contract\Events\EventManager $dispatcher
@param string                                          $eventName

@return void

Adds this pattern s listener to an event .


public function unbind(EventManagerContract $dispatcher): void
    {
        foreach ($this->events as $eventName => $value) {
            $dispatcher->detach($eventName, $this->getListener());
        }

        $this->events = [];
    }

public function unbind ( EventManagerContract $ dispatcher ) : void { foreach ( $ this -> events as $ eventName => $ value ) { $ dispatcher -> detach ( $ eventName , $ this -> getListener ( ) ) ; } $ this -> events = [ ] ; }

Removes this pattern's listener from all events to which it was
previously added.

@param \Viserio\Component\Contract\Events\EventManager $dispatcher

@return void

Removes this pattern s listener from all events to which it was previously added .


private function createRegex(string $eventPattern): string
    {
        return \sprintf('/^%s$/i', \preg_replace(
            \array_keys(self::$wildcardsSeparators),
            \array_values(self::$wildcardsSeparators),
            \str_replace('\#', '#', \preg_quote($eventPattern, '/'))
        ));
    }

private function createRegex ( string $ eventPattern ) : string { return \ sprintf ( '/^%s$/i' , \ preg_replace ( \ array_keys ( self :: $ wildcardsSeparators ) , \ array_values ( self :: $ wildcardsSeparators ) , \ str_replace ( '\#' , '#' , \ preg_quote ( $ eventPattern , '/' ) ) ) ) ; }

Transforms an event pattern into a regular expression.

@param string $eventPattern

@return string

Transforms an event pattern into a regular expression .


public function offsetGet($key)
    {
        $value = Arr::get($this->data, $key);

        if (\is_array($value)) {
            $value = $this->processParameters($value);
        } else {
            $value = $this->processParameter($value);
        }

        return $value;
    }

public function offsetGet ( $ key ) { $ value = Arr :: get ( $ this -> data , $ key ) ; if ( \ is_array ( $ value ) ) { $ value = $ this -> processParameters ( $ value ) ; } else { $ value = $ this -> processParameter ( $ value ) ; } return $ value ; }

Get a value from a nested array based on a separated key.

@param string $key

@return mixed

Get a value from a nested array based on a separated key .


public function offsetSet($key, $value): self
    {
        $this->data = Arr::set($this->data, $key, $value);

        return $this;
    }

public function offsetSet ( $ key , $ value ) : self { $ this -> data = Arr :: set ( $ this -> data , $ key , $ value ) ; return $ this ; }

Set nested array values based on a separated key.

@param string $key
@param mixed  $value

@return $this

Set nested array values based on a separated key .


private function processParameters(array $data): array
    {
        \array_walk_recursive($data, function (&$parameter): void {
            // @codeCoverageIgnoreStart
            if (\is_array($parameter)) {
                $parameter = $this->processParameters($parameter);
            // @codeCoverageIgnoreEnd
            } else {
                $parameter = $this->processParameter($parameter);
            }
        });

        return $data;
    }

private
function
processParameters
(
array
$
data
)
:
array
{
\
array_walk_recursive
(
$
data
,
function
(
&
$
parameter
)
:
void
{
// @codeCoverageIgnoreStart
if
(
\
is_array
(
$
parameter
)
)
{
$
parameter
=
$
this
->
processParameters
(
$
parameter
)
;
// @codeCoverageIgnoreEnd
}
else
{
$
parameter
=
$
this
->
processParameter
(
$
parameter
)
;
}
}
)
;
return
$
data
;
}

Process array through all parameter processors.

@param array $data

@return array

Process array through all parameter processors .


private function processParameter($parameter)
    {
        foreach ($this->parameterProcessors as $processor) {
            if ($processor->supports((string) $parameter)) {
                return $processor->process($parameter);
            }
        }

        return $parameter;
    }

private function processParameter ( $ parameter ) { foreach ( $ this -> parameterProcessors as $ processor ) { if ( $ processor -> supports ( ( string ) $ parameter ) ) { return $ processor -> process ( $ parameter ) ; } } return $ parameter ; }

Process through all parameter processors.

@param mixed $parameter

@return mixed

Process through all parameter processors .


public function render(ConsoleOutputContract $output, Throwable $exception): void
    {
        $exceptionMessage = $exception->getMessage();
        $exceptionName    = \get_class($exception);

        $output->writeln('');
        $output->writeln(\sprintf(
            '<bg=red;options=bold>%s</> : <comment>%s</>',
            $exceptionName,
            $exceptionMessage
        ));
        $output->writeln('');

        $this->renderEditor($output, $exception);
        $this->renderTrace($output, $exception);
    }

Render an exception to the console.

@param \Viserio\Component\Contract\Exception\ConsoleOutput $output
@param \Throwable                                          $exception

@return void


private function renderEditor(ConsoleOutputContract $output, Throwable $exception): void
    {
        $output->writeln(\sprintf(
            'at <fg=green>%s</>' . ':<fg=green>%s</>',
            $exception->getFile(),
            $exception->getLine()
        ));

        $range = self::getFileLines(
            $exception->getFile(),
            $exception->getLine() - 5,
            10
        );

        foreach ($range as $k => $code) {
            $line = $k + 1;
            $code = $exception->getLine() === $line ? \sprintf('<bg=red>%s</>', $code) : $code;
            $output->writeln(\sprintf('%s: %s', $line, $code));
        }

        $output->writeln('');
    }

private
function
renderEditor
(
ConsoleOutputContract
$
output
,
Throwable
$
exception
)
:
void
{
$
output
->
writeln
(
\
sprintf
(
'at <fg=green>%s</>'
.
':<fg=green>%s</>'
,
$
exception
->
getFile
(
)
,
$
exception
->
getLine
(
)
)
)
;
$
range
=
self
::
getFileLines
(
$
exception
->
getFile
(
)
,
$
exception
->
getLine
(
)
5
,
10
)
;
foreach
(
$
range
as
$
k
=>
$
code
)
{
$
line
=
$
k
+
1
;
$
code
=
$
exception
->
getLine
(
)
===
$
line
\
sprintf
(
'<bg=red>%s</>'
,
$
code
)
:
$
code
;
$
output
->
writeln
(
\
sprintf
(
'%s: %s'
,
$
line
,
$
code
)
)
;
}
$
output
->
writeln
(
''
)
;
}

Renders the editor containing the code that was the
origin of the exception.

@param \Viserio\Component\Contract\Exception\ConsoleOutput $output
@param \Throwable                                          $exception

@return void

Renders the editor containing the code that was the origin of the exception .


private function renderTrace(ConsoleOutputContract $output, Throwable $exception): void
    {
        $output->writeln('<comment>Exception trace:</comment>');
        $output->writeln('');

        $count = 0;

        foreach ($this->getFrames($exception) as $i => $frame) {
            if ($i > static::VERBOSITY_NORMAL_FRAMES &&
                $output->getVerbosity() < ConsoleOutputContract::VERBOSITY_VERBOSE
            ) {
                $output->writeln('');
                $output->writeln(
                    '<info>Please use the argument <fg=red>-v</> to see all trace.</info>'
                );

                break;
            }

            $class    = isset($frame['class']) ? $frame['class'] . '::' : '';
            $function = $frame['function'] ?? '';

            if ($class !== '' && $function !== '') {
                $output->writeln(\sprintf(
                    '<comment><fg=cyan>%s</>%s%s(%s)</comment>',
                    \str_pad((string) ((int) $i + 1), 4, ' '),
                    $class,
                    $function,
                    isset($frame['args']) ? self::formatsArgs($frame['args']) : ''
                ));
            }

            if (isset($frame['file'], $frame['line'])) {
                $output->writeln(\sprintf(
                    '    <fg=green>%s</>:<fg=green>%s</>',
                    $frame['file'],
                    $frame['line']
                ));
            }

            if ($count !== 4) {
                $output->writeln('');
            }

            $count++;
        }
    }

Renders the trace of the exception.

@param \Viserio\Component\Contract\Exception\ConsoleOutput $output
@param \Throwable                                          $exception

@return void


private function getTrace(Throwable $exception): array
    {
        $traces = $exception->getTrace();

        // Get trace from xdebug if enabled, failure exceptions only trace to the shutdown handler by default
        if (! $exception instanceof ErrorException) {
            return $traces;
        }

        if (! self::isLevelFatal($exception->getSeverity())) {
            return $traces;
        }

        if (! \extension_loaded('xdebug') || ! \xdebug_is_enabled()) {
            return [];
        }

        // Use xdebug to get the full stack trace and remove the shutdown handler stack trace
        $stack  = \array_reverse(\xdebug_get_function_stack());
        $trace  = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);

        return \array_diff_key($stack, $trace);
    }

Gets the backtrace from an exception.

If xdebug is installed

@param \Throwable $exception

@return array


private function getFrames(Throwable $exception): array
    {
        $frames = $this->getTrace($exception);

        // Fill empty line/file info for call_user_func_array usages (PHP Bug #44428)
        foreach ($frames as $k => $frame) {
            if (empty($frame['file'])) {
                // Default values when file and line are missing
                $file      = '[internal]';
                $line      = 0;
                $nextFrame = \count($frames[$k + 1]) !== 0 ? $frames[$k + 1] : [];

                if ($this->isValidNextFrame($nextFrame)) {
                    $file = $nextFrame['file'];
                    $line = $nextFrame['line'];
                }

                $frames[$k]['file'] = $file;
                $frames[$k]['line'] = $line;
            }

            $frames['function'] = $frame['function'] ?? '';
        }

        // Find latest non-error handling frame index ($i) used to remove error handling frames
        $i = 0;

        foreach ($frames as $k => $frame) {
            if (isset($frame['file'], $frame['line']) &&
                $frame['file'] === $exception->getFile() &&
                $frame['line'] === $exception->getLine()
            ) {
                $i = $k;
            }
        }

        // Remove error handling frames
        if ($i > 0) {
            \array_splice($frames, 0, $i);
        }

        \array_unshift($frames, $this->getFrameFromException($exception));

        // show the last 5 frames
        return \array_slice($frames, 0, 5);
    }

Returns an iterator for the inspected exception's
frames.

@param \Throwable $exception

@return array

Returns an iterator for the inspected exception s frames .


private static function formatsArgs(array $arguments, bool $recursive = true): string
    {
        $result = [];

        foreach ($arguments as $argument) {
            switch (true) {
                case \is_string($argument):
                    $result[] = '"' . $argument . '"';

                    break;
                case \is_array($argument):
                    $associative = \array_keys($argument) !== \range(0, \count($argument) - 1);

                    if ($recursive && $associative && \count($argument) <= 5) {
                        $result[] = '[' . self::formatsArgs($argument, false) . ']';
                    }

                    break;
                case \is_object($argument):
                    $class    = \get_class($argument);
                    $result[] = "Object(${class})";

                    break;
            }
        }

        return \implode(', ', $result);
    }

private
static
function
formatsArgs
(
array
$
arguments
,
bool
$
recursive
=
true
)
:
string
{
$
result
=
[
]
;
foreach
(
$
arguments
as
$
argument
)
{
switch
(
true
)
{
case
\
is_string
(
$
argument
)
:
$
result
[
]
=
'"'
.
$
argument
.
'"'
;
break
;
case
\
is_array
(
$
argument
)
:
$
associative
=
\
array_keys
(
$
argument
)
!==
\
range
(
0
,
\
count
(
$
argument
)
1
)
;
if
(
$
recursive
&&
$
associative
&&
\
count
(
$
argument
)
<=
5
)
{
$
result
[
]
=
'['
.
self
::
formatsArgs
(
$
argument
,
false
)
.
']'
;
}
break
;
case
\
is_object
(
$
argument
)
:
$
class
=
\
get_class
(
$
argument
)
;
$
result
[
]
=
"Object(${class})"
;
break
;
}
}
return
\
implode
(
', '
,
$
result
)
;
}

Format the given function args to a string.

@param array $arguments
@param bool  $recursive

@return string

Format the given function args to a string .


private static function getFileLines(string $filePath, int $start, int $length): ?array
    {
        if (($contents = self::getFileContents($filePath)) !== null) {
            $lines = \explode("\n", $contents);

            if ($start < 0) {
                $start = 0;
            }

            return \array_slice($lines, $start, $length, true);
        }
    }

private static function getFileLines ( string $ filePath , int $ start , int $ length ) : ? array { if ( ( $ contents = self :: getFileContents ( $ filePath ) ) !== null ) { $ lines = \ explode ( "\n" , $ contents ) ; if ( $ start < 0 ) { $ start = 0 ; } return \ array_slice ( $ lines , $ start , $ length , true ) ; } }

Returns the contents of the file for this frame as an
array of lines, and optionally as a clamped range of lines.

@param string $filePath
@param int    $start
@param int    $length

@return null|string[]

Returns the contents of the file for this frame as an array of lines and optionally as a clamped range of lines .


private static function getFileContents(string $filePath): ?string
    {
        // Leave the stage early when 'Unknown' is passed
        // this would otherwise raise an exception when
        // open_basedir is enabled.
        if ($filePath === 'Unknown') {
            return null;
        }

        // Return null if the file doesn't actually exist.
        if (! \is_file($filePath)) {
            return null;
        }

        return \file_get_contents($filePath);
    }

Returns the full contents of the file for this frame,
if it's known.

@param string $filePath

@return null|string

Returns the full contents of the file for this frame if it s known .


protected function normalizeName(string $name): string
    {
        $delimiter = FinderContract::HINT_PATH_DELIMITER;

        if (\mb_strpos($name, $delimiter) === false) {
            return \str_replace('/', '.', $name);
        }

        [$namespace, $name] = \explode($delimiter, $name);

        return $namespace . $delimiter . \str_replace('/', '.', $name);
    }

protected function normalizeName ( string $ name ) : string { $ delimiter = FinderContract :: HINT_PATH_DELIMITER ; if ( \ mb_strpos ( $ name , $ delimiter ) === false ) { return \ str_replace ( '/' , '.' , $ name ) ; } [ $ namespace , $ name ] = \ explode ( $ delimiter , $ name ) ; return $ namespace . $ delimiter . \ str_replace ( '/' , '.' , $ name ) ; }

Normalize a view name.

@param string $name

@return string


public function resolve($subject, array $parameters = [])
    {
        if ($this->isClass($subject)) {
            return $this->resolveClass($subject, $parameters);
        }

        if ($this->isMethod($subject)) {
            return $this->resolveMethod($subject, $parameters);
        }

        if ($this->isFunction($subject)) {
            return $this->resolveFunction($subject, $parameters);
        }

        $subject = \is_object($subject) ? \get_class($subject) : $subject;

        throw new BindingResolutionException(\sprintf(
            '[%s] is not resolvable. Build stack : [%s]',
            $subject,
            \implode(', ', $this->buildStack)
        ));
    }

Resolves an entry by its name. If given a class name, it will return a new instance of that class.

@param mixed $subject
@param array $parameters

@throws \Viserio\Component\Contract\Container\Exception\BindingResolutionException
@throws \Viserio\Component\Contract\Container\Exception\CyclicDependencyException
@throws \ReflectionException

@return mixed|object

Resolves an entry by its name . If given a class name it will return a new instance of that class .


public function resolveClass(string $class, array $parameters = []): object
    {
        $reflectionClass = new ReflectionClass($class);

        if (! $reflectionClass->isInstantiable()) {
            throw new BindingResolutionException(
                \sprintf(
                    'Unable to reflect on the class [%s], does the class exist and is it properly autoloaded?',
                    $class
                )
            );
        }

        if (\in_array($class, $this->buildStack, true)) {
            $this->buildStack[] = $class;

            throw new CyclicDependencyException($class, $this->buildStack);
        }

        $reflectionMethod   = $reflectionClass->getConstructor();
        $this->buildStack[] = $reflectionClass->name;

        if ($reflectionMethod) {
            $reflectionParameters = $reflectionMethod->getParameters();
            $parameters           = $this->resolveParameters($reflectionParameters, $parameters);
        }

        \array_pop($this->buildStack);

        return $reflectionClass->newInstanceArgs($parameters);
    }

Resolve a class.

@param string $class
@param array  $parameters

@throws \Viserio\Component\Contract\Container\Exception\BindingResolutionException
@throws \Viserio\Component\Contract\Container\Exception\CyclicDependencyException
@throws \ReflectionException

@return object


public function resolveMethod($method, array $parameters = [])
    {
        $reflectionMethod     = $this->getMethodReflector($method);
        $reflectionParameters = $reflectionMethod->getParameters();
        $this->buildStack[]   = $reflectionMethod->name;
        $resolvedParameters   = $this->resolveParameters($reflectionParameters, $parameters);

        \array_pop($this->buildStack);

        return $method(...$resolvedParameters);
    }

public function resolveMethod ( $ method , array $ parameters = [ ] ) { $ reflectionMethod = $ this -> getMethodReflector ( $ method ) ; $ reflectionParameters = $ reflectionMethod -> getParameters ( ) ; $ this -> buildStack [ ] = $ reflectionMethod -> name ; $ resolvedParameters = $ this -> resolveParameters ( $ reflectionParameters , $ parameters ) ; \ array_pop ( $ this -> buildStack ) ; return $ method ( ... $ resolvedParameters ) ; }

Resolve a method.

@param array|string $method
@param array        $parameters

@throws \Viserio\Component\Contract\Container\Exception\BindingResolutionException
@throws \Viserio\Component\Contract\Container\Exception\CyclicDependencyException
@throws \ReflectionException

@return mixed


protected function resolveParameter(ReflectionParameter $parameter, array $parameters = [])
    {
        $name  = $parameter->name;
        $index = $parameter->getPosition();

        if (isset($parameters[$name])) {
            return $parameters[$name];
        }

        if (isset($parameters[$index])) {
            return $parameters[$index];
        }

        if ($class = $parameter->getClass()) {
            return $this->resolve($class->name);
        }

        if ($parameter->isDefaultValueAvailable()) {
            return $parameter->getDefaultValue();
        }

        throw new BindingResolutionException(\sprintf(
            'Unresolvable dependency resolving [%s] in [%s]',
            $parameter,
            \end($this->buildStack)
        ));
    }

Resolve a parameter.

@param \ReflectionParameter $parameter
@param array                $parameters

@throws \Viserio\Component\Contract\Container\Exception\BindingResolutionException
@throws \Viserio\Component\Contract\Container\Exception\CyclicDependencyException

@return mixed


protected function resolveParameters(array $reflectionParameters, array $parameters = []): array
    {
        $dependencies = [];

        foreach ($reflectionParameters as $key => $parameter) {
            $dependencies[] = $this->resolveParameter($parameter, $parameters);
        }

        return $this->mergeParameters($dependencies, $parameters);
    }

protected function resolveParameters ( array $ reflectionParameters , array $ parameters = [ ] ) : array { $ dependencies = [ ] ; foreach ( $ reflectionParameters as $ key => $ parameter ) { $ dependencies [ ] = $ this -> resolveParameter ( $ parameter , $ parameters ) ; } return $ this -> mergeParameters ( $ dependencies , $ parameters ) ; }

Resolve an array of \ReflectionParameter parameters.

@param array $reflectionParameters
@param array $parameters

@throws \Viserio\Component\Contract\Container\Exception\BindingResolutionException
@throws \Viserio\Component\Contract\Container\Exception\CyclicDependencyException

@return array

Resolve an array of \ ReflectionParameter parameters .


protected function getMethodReflector($method): ReflectionMethod
    {
        if (\is_string($method)) {
            return new ReflectionMethod($method);
        }

        return new ReflectionMethod($method[0], $method[1]);
    }

protected function getMethodReflector ( $ method ) : ReflectionMethod { if ( \ is_string ( $ method ) ) { return new ReflectionMethod ( $ method ) ; } return new ReflectionMethod ( $ method [ 0 ] , $ method [ 1 ] ) ; }

Get the reflection object for a method.

@param array|string $method

@throws \ReflectionException

@return \ReflectionMethod

Get the reflection object for a method .


protected function isFunction($value): bool
    {
        return \is_callable($value) && ($value instanceof Closure || (\is_string($value) && \function_exists($value)));
    }

protected function isFunction ( $ value ) : bool { return \ is_callable ( $ value ) && ( $ value instanceof Closure || ( \ is_string ( $ value ) && \ function_exists ( $ value ) ) ) ; }

Check if something is a function.

@param mixed $value

@return bool


private function mergeParameters(array $rootParameters, array $parameters = []): array
    {
        foreach ($parameters as $key => $value) {
            if (\is_int($key) && ! isset($rootParameters[$key])) {
                $rootParameters[$key] = $value;
            }
        }

        return $rootParameters;
    }

private function mergeParameters ( array $ rootParameters , array $ parameters = [ ] ) : array { foreach ( $ parameters as $ key => $ value ) { if ( \ is_int ( $ key ) && ! isset ( $ rootParameters [ $ key ] ) ) { $ rootParameters [ $ key ] = $ value ; } } return $ rootParameters ; }

Merge some dynamically resolved parameters with some others provided parameters by the user.

@param array $rootParameters
@param array $parameters

@return array

Merge some dynamically resolved parameters with some others provided parameters by the user .


public function write(string $path, $contents, array $config = []): bool
    {
        $contents = $this->encryptString($contents);

        return $this->adapter->write($path, $contents, $config);
    }

public function write ( string $ path , $ contents , array $ config = [ ] ) : bool { $ contents = $ this -> encryptString ( $ contents ) ; return $ this -> adapter -> write ( $ path , $ contents , $ config ) ; }

Write a new file.

@param string $path     the path of the new file
@param string $contents the file contents
@param array  $config   an optional configuration array

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException

@return bool true on success, false on failure


public function put(string $path, $contents, array $config = []): bool
    {
        if (\is_resource($contents)) {
            $contents = $this->encryptStream($contents);
        } else {
            $contents = $this->encryptString($contents);
        }

        return $this->adapter->put($path, $contents, $config);
    }

public function put ( string $ path , $ contents , array $ config = [ ] ) : bool { if ( \ is_resource ( $ contents ) ) { $ contents = $ this -> encryptStream ( $ contents ) ; } else { $ contents = $ this -> encryptString ( $ contents ) ; } return $ this -> adapter -> put ( $ path , $ contents , $ config ) ; }

Write the contents of a file.

@param string          $path
@param resource|string $contents
@param array           $config   an optional configuration array

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException

@return bool


public function updateStream(string $path, $resource, array $config = []): bool
    {
        $resource = $this->encryptStream($resource);

        return $this->adapter->updateStream($path, $resource, $config);
    }

public function updateStream ( string $ path , $ resource , array $ config = [ ] ) : bool { $ resource = $ this -> encryptStream ( $ resource ) ; return $ this -> adapter -> updateStream ( $ path , $ resource , $ config ) ; }

Update a file using a stream.

@param string   $path
@param resource $resource
@param array    $config

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException

@return bool


private function decryptStream($resource)
    {
        $out = \fopen('php://memory', 'r+b');

        if ($resource !== false) {
            try {
                File::decrypt($resource, $out, $this->key);
            } catch (FileAccessDenied $exception) {
                throw new FileAccessDeniedException($exception->getMessage(), $exception->getCode(), $exception);
            } catch (FileModified $exception) {
                throw new FileModifiedException($exception->getMessage(), $exception->getCode(), $exception);
            }

            \rewind($out);
        }

        return $out;
    }

private function decryptStream ( $ resource ) { $ out = \ fopen ( 'php://memory' , 'r+b' ) ; if ( $ resource !== false ) { try { File :: decrypt ( $ resource , $ out , $ this -> key ) ; } catch ( FileAccessDenied $ exception ) { throw new FileAccessDeniedException ( $ exception -> getMessage ( ) , $ exception -> getCode ( ) , $ exception ) ; } catch ( FileModified $ exception ) { throw new FileModifiedException ( $ exception -> getMessage ( ) , $ exception -> getCode ( ) , $ exception ) ; } \ rewind ( $ out ) ; } return $ out ; }

Decrypts a stream.

@param false|resource $resource the stream to decrypt

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException

@return resource


private function encryptStream($resource)
    {
        $out = \fopen('php://temp', 'w+b');

        if ($resource !== false) {
            try {
                File::encrypt($resource, $out, $this->key);
            } catch (FileAccessDenied $exception) {
                throw new FileAccessDeniedException($exception->getMessage(), $exception->getCode(), $exception);
            } catch (FileModified $exception) {
                throw new FileModifiedException($exception->getMessage(), $exception->getCode(), $exception);
            }

            \rewind($out);
        }

        return $out;
    }

private function encryptStream ( $ resource ) { $ out = \ fopen ( 'php://temp' , 'w+b' ) ; if ( $ resource !== false ) { try { File :: encrypt ( $ resource , $ out , $ this -> key ) ; } catch ( FileAccessDenied $ exception ) { throw new FileAccessDeniedException ( $ exception -> getMessage ( ) , $ exception -> getCode ( ) , $ exception ) ; } catch ( FileModified $ exception ) { throw new FileModifiedException ( $ exception -> getMessage ( ) , $ exception -> getCode ( ) , $ exception ) ; } \ rewind ( $ out ) ; } return $ out ; }

Encrypts a stream.

@param false|resource $resource the stream to encrypt

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException

@return resource


private function decryptString(string $contents): string
    {
        $resource = $this->getStreamFromString($contents);

        return (string) \stream_get_contents($this->decryptStream($resource));
    }

private function decryptString ( string $ contents ) : string { $ resource = $ this -> getStreamFromString ( $ contents ) ; return ( string ) \ stream_get_contents ( $ this -> decryptStream ( $ resource ) ) ; }

Decrypts a string.

@param string $contents the string to decrypt

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileNotFoundException

@return string


private function encryptString(string $contents): string
    {
        $resource = $this->getStreamFromString($contents);

        return (string) \stream_get_contents($this->encryptStream($resource));
    }

private function encryptString ( string $ contents ) : string { $ resource = $ this -> getStreamFromString ( $ contents ) ; return ( string ) \ stream_get_contents ( $ this -> encryptStream ( $ resource ) ) ; }

Encrypts a string.

@param string $contents the string to encrypt

@throws \ParagonIE\Halite\Alerts\CannotPerformOperation
@throws \ParagonIE\Halite\Alerts\FileError
@throws \ParagonIE\Halite\Alerts\InvalidDigestLength
@throws \ParagonIE\Halite\Alerts\InvalidKey
@throws \ParagonIE\Halite\Alerts\InvalidMessage
@throws \ParagonIE\Halite\Alerts\InvalidType
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileModifiedException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileNotFoundException

@return string


private function getStreamFromString(string $contents)
    {
        $path = \bin2hex(\random_bytes(16));

        $this->adapter->write($path, $contents);

        \sodium_memzero($contents);

        $streamContent = $this->adapter->readStream($path);

        $this->adapter->delete($path);

        if ($streamContent !== false) {
            return $streamContent;
        }

        throw new RuntimeException('Created file for string content cant be read.');
    }

Returns a stream representation of a string.

@param string $contents The string

@throws \Viserio\Component\Contract\Filesystem\Exception\RuntimeException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileNotFoundException
@throws \Viserio\Component\Contract\Filesystem\Exception\FileAccessDeniedException

@return resource

Returns a stream representation of a string .


public static function createTransportFactory(ContainerInterface $container): TransportFactory
    {
        $transport = new TransportFactory();

        if ($container->has(LoggerInterface::class)) {
            $transport->setLogger($container->get(LoggerInterface::class));
        }

        return $transport;
    }

public static function createTransportFactory ( ContainerInterface $ container ) : TransportFactory { $ transport = new TransportFactory ( ) ; if ( $ container -> has ( LoggerInterface :: class ) ) { $ transport -> setLogger ( $ container -> get ( LoggerInterface :: class ) ) ; } return $ transport ; }

Create a new transport factory.

@param \Psr\Container\ContainerInterface $container

@return \Viserio\Component\Mail\TransportFactory


public static function createMailManager(ContainerInterface $container): MailManager
    {
        $manager = new MailManager($container->get('config'), $container->get(TransportFactory::class));
        $manager->setContainer($container);

        if ($container->has(ViewFactoryContract::class)) {
            $manager->setViewFactory($container->get(ViewFactoryContract::class));
        }

        if ($container->has(EventManagerContract::class)) {
            $manager->setEventManager($container->get(EventManagerContract::class));
        }

        return $manager;
    }

public static function createMailManager ( ContainerInterface $ container ) : MailManager { $ manager = new MailManager ( $ container -> get ( 'config' ) , $ container -> get ( TransportFactory :: class ) ) ; $ manager -> setContainer ( $ container ) ; if ( $ container -> has ( ViewFactoryContract :: class ) ) { $ manager -> setViewFactory ( $ container -> get ( ViewFactoryContract :: class ) ) ; } if ( $ container -> has ( EventManagerContract :: class ) ) { $ manager -> setEventManager ( $ container -> get ( EventManagerContract :: class ) ) ; } return $ manager ; }

Create a new swift mailer manager.

@param \Psr\Container\ContainerInterface $container

@return \Viserio\Component\Mail\MailManager


public static function getVersionNumber(DOMDocument $dom): string
    {
        /** @var \DOMNode $xliff */
        foreach ($dom->getElementsByTagName('xliff') as $xliff) {
            if (($version = $xliff->attributes->getNamedItem('version')) !== null) {
                return $version->nodeValue;
            }

            if ($namespace = $xliff->attributes->getNamedItem('xmlns')) {
                if (\substr_compare('urn:oasis:names:tc:xliff:document:', $namespace, 0, 34) !== 0) {
                    throw new InvalidArgumentException(\sprintf('Not a valid XLIFF namespace [%s].', $namespace));
                }

                return \mb_substr($namespace, 34);
            }
        }

        return '1.2'; // Falls back to v1.2
    }

public
static
function
getVersionNumber
(
DOMDocument
$
dom
)
:
string
{
/** @var \DOMNode $xliff */
foreach
(
$
dom
->
getElementsByTagName
(
'xliff'
)
as
$
xliff
)
{
if
(
(
$
version
=
$
xliff
->
attributes
->
getNamedItem
(
'version'
)
)
!==
)
{
return
$
version
->
nodeValue
;
}
if
(
$
namespace
=
$
xliff
->
attributes
->
getNamedItem
(
'xmlns'
)
)
{
if
(
\
substr_compare
(
'urn:oasis:names:tc:xliff:document:'
,
$
namespace
,
0
,
34
)
!==
0
)
{
throw
new
InvalidArgumentException
(
\
sprintf
(
'Not a valid XLIFF namespace [%s].'
,
$
namespace
)
)
;
}
return
\
mb_substr
(
$
namespace
,
34
)
;
}
}
return
'1.2'
;
// Falls back to v1.2
}

Gets xliff file version based on the root "version" attribute.
Defaults to 1.2 for backwards compatibility.

@param \DOMDocument $dom

@throws \Viserio\Component\Contract\Parser\Exception\InvalidArgumentException;

@return string

Gets xliff file version based on the root version attribute . Defaults to 1 . 2 for backwards compatibility .


public static function getSchema(string $xliffVersion): string
    {
        if ($xliffVersion === '1.2') {
            $xmlUri       = 'http://www.w3.org/2001/xml.xsd';
            $schemaSource = \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Resource' . \DIRECTORY_SEPARATOR . 'schemas' . \DIRECTORY_SEPARATOR . 'xliff-core' . \DIRECTORY_SEPARATOR . 'xliff-core-1.2-strict.xsd';
        } elseif ($xliffVersion === '2.0') {
            $xmlUri       = 'informativeCopiesOf3rdPartySchemas/w3c/xml.xsd';
            $schemaSource = \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Resource' . \DIRECTORY_SEPARATOR . 'schemas' . \DIRECTORY_SEPARATOR . 'xliff-core' . \DIRECTORY_SEPARATOR . 'xliff-core-2.0.xsd';
        } else {
            throw new InvalidArgumentException(\sprintf('No support implemented for loading XLIFF version [%s].', $xliffVersion));
        }

        return self::fixLocation(\file_get_contents($schemaSource), $xmlUri);
    }

Get the right xliff schema from version.

@param string $xliffVersion

@throws \Viserio\Component\Contract\Parser\Exception\InvalidArgumentException;

@return string

Get the right xliff schema from version .


private static function fixLocation(string $schemaSource, string $xmlUri): string
    {
        $newPath = \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Resource' . \DIRECTORY_SEPARATOR . 'schemas' . \DIRECTORY_SEPARATOR . 'xliff-core' . \DIRECTORY_SEPARATOR . 'xml.xsd';
        $parts   = \explode(\DIRECTORY_SEPARATOR, $newPath);

        if (\mb_stripos($newPath, 'phar://') === 0 && ($tmpFile = \tempnam(\sys_get_temp_dir(), 'narrowspark')) !== false) {
            \copy($newPath, $tmpFile);

            $parts = \explode(\DIRECTORY_SEPARATOR, $tmpFile);
        }

        $drive   = '\\' === \DIRECTORY_SEPARATOR ? \array_shift($parts) . '/' : '';
        $newPath = 'file:///' . $drive . \implode('/', \array_map('rawurlencode', $parts));

        return \str_replace($xmlUri, $newPath, $schemaSource);
    }

private static function fixLocation ( string $ schemaSource , string $ xmlUri ) : string { $ newPath = \ dirname ( __DIR__ , 1 ) . \ DIRECTORY_SEPARATOR . 'Resource' . \ DIRECTORY_SEPARATOR . 'schemas' . \ DIRECTORY_SEPARATOR . 'xliff-core' . \ DIRECTORY_SEPARATOR . 'xml.xsd' ; $ parts = \ explode ( \ DIRECTORY_SEPARATOR , $ newPath ) ; if ( \ mb_stripos ( $ newPath , 'phar://' ) === 0 && ( $ tmpFile = \ tempnam ( \ sys_get_temp_dir ( ) , 'narrowspark' ) ) !== false ) { \ copy ( $ newPath , $ tmpFile ) ; $ parts = \ explode ( \ DIRECTORY_SEPARATOR , $ tmpFile ) ; } $ drive = '\\' === \ DIRECTORY_SEPARATOR ? \ array_shift ( $ parts ) . '/' : '' ; $ newPath = 'file:///' . $ drive . \ implode ( '/' , \ array_map ( 'rawurlencode' , $ parts ) ) ; return \ str_replace ( $ xmlUri , $ newPath , $ schemaSource ) ; }

Internally changes the URI of a dependent xsd to be loaded locally.

@param string $schemaSource Current content of schema file
@param string $xmlUri       External URI of XML to convert to local

@return string

Internally changes the URI of a dependent xsd to be loaded locally .


private function parseVisibility(string $path, string $visibility = null): ?int
    {
        $type = '';

        if (\is_file($path)) {
            $type = 'file';
        } elseif (\is_dir($path)) {
            $type = 'dir';
        }

        if ($visibility === null || $type === '') {
            return null;
        }

        if ($visibility === FilesystemContract::VISIBILITY_PUBLIC) {
            return $this->permissions[$type]['public'];
        }

        if ($visibility === FilesystemContract::VISIBILITY_PRIVATE) {
            return $this->permissions[$type]['private'];
        }

        throw new InvalidArgumentException('Unknown visibility: ' . $visibility);
    }

private
function
parseVisibility
(
string
$
path
,
string
$
visibility
=
)
:
int
{
$
type
=
''
;
if
(
\
is_file
(
$
path
)
)
{
$
type
=
'file'
;
}
elseif
(
\
is_dir
(
$
path
)
)
{
$
type
=
'dir'
;
}
if
(
$
visibility
===
||
$
type
===
''
)
{
return
;
}
if
(
$
visibility
===
FilesystemContract
::
VISIBILITY_PUBLIC
)
{
return
$
this
->
permissions
[
$
type
]
[
'public'
]
;
}
if
(
$
visibility
===
FilesystemContract
::
VISIBILITY_PRIVATE
)
{
return
$
this
->
permissions
[
$
type
]
[
'private'
]
;
}
throw
new
InvalidArgumentException
(
'Unknown visibility: '
.
$
visibility
)
;
}

Parse the given visibility value.

@param string      $path
@param null|string $visibility

@throws \Viserio\Component\Contract\Filesystem\Exception\InvalidArgumentException

@return null|int


public function sanitize(array $rules, array $data): array
    {
        [$data, $rules] = $this->runGlobalSanitizers($rules, $data);

        $availableRules = \array_intersect_key($rules, \array_flip(array_keys($data)));

        foreach ($availableRules as $field => $ruleset) {
            $data[$field] = $this->sanitizeField($data, $field, $ruleset);
        }

        return $data;
    }

public function sanitize ( array $ rules , array $ data ) : array { [ $ data , $ rules ] = $ this -> runGlobalSanitizers ( $ rules , $ data ) ; $ availableRules = \ array_intersect_key ( $ rules , \ array_flip ( array_keys ( $ data ) ) ) ; foreach ( $ availableRules as $ field => $ ruleset ) { $ data [ $ field ] = $ this -> sanitizeField ( $ data , $ field , $ ruleset ) ; } return $ data ; }

Sanitize a dataset using rules.

@param array $rules
@param array $data

@return array


private function runGlobalSanitizers(array $rules, array $data): array
    {
        // Bail out if no global rules were found.
        if (! isset($rules['*'])) {
            return [$data, $rules];
        }

        // Get the global rules and remove them from the main ruleset.
        $globalRules = $rules['*'];

        unset($rules['*']);

        // Execute the global sanitiers on each field.
        foreach ($data as $field => $value) {
            $data[$field] = $this->sanitizeField($data, $field, $globalRules);
        }

        return [$data, $rules];
    }

Apply global sanitizer rules.

@param array $rules
@param array $data

@return array


private function sanitizeField(array $data, string $field, $ruleset): string
    {
        if (! \is_string($ruleset) && ! \is_array($ruleset)) {
            throw new InvalidArgumentException(\sprintf(
                'The ruleset parameter must be of type string or array, [%s] given.',
                \is_object($ruleset) ? \get_class($ruleset) : \gettype($ruleset)
            ));
        }

        // If we have a piped ruleset, explode it.
        if (\is_string($ruleset)) {
            $ruleset = \explode('|', $ruleset);
        }

        // Get value from data array.
        $value = $data[$field];

        foreach ($ruleset as $rule) {
            $parametersSet = [];

            if (\strpos($rule, ':') !== false) {
                [$rule, $parameters] = \explode(':', $rule);

                $parametersSet = \explode(',', $parameters);
            }

            \array_unshift($parametersSet, $value);

            $sanitizers = $rule;

            // Retrieve a sanitizer by key.
            if (isset($this->sanitizers[$rule])) {
                $sanitizers = $this->sanitizers[$rule];
            }

            // Execute the sanitizer to mutate the value.
            $value = $this->executeSanitizer($sanitizers, $parametersSet);
        }

        return $value;
    }

Execute sanitization over a specific field.

@param array        $data
@param string       $field
@param string|array $ruleset

@return string

Execute sanitization over a specific field .


private function executeSanitizer($sanitizer, array $parameters): string
    {
        if (\is_callable($sanitizer)) {
            return $sanitizer(...$parameters);
        }

        if ($this->container !== null) {
            // Transform a container resolution to a callback.
            $sanitizer = $this->resolveCallback($sanitizer);

            return $sanitizer(...$parameters);
        }

        // If the sanitizer can't be called, return the passed value.
        return $parameters[0];
    }

Execute a sanitizer using the appropriate method.

@param callable|string|\Closure $sanitizer
@param array                    $parameters

@return string

Execute a sanitizer using the appropriate method .


private function resolveCallback(string $callback): array
    {
        $segments = explode('@', $callback);
        $method = \count($segments) === 2 ? $segments[1] : 'sanitize';

        // Return the constructed callback.
        return [$this->container->get($segments[0]), $method];
    }

private
function
resolveCallback
(
string
$
callback
)
:
array
{
$
segments
=
explode
(
'@'
,
$
callback
)
;
$
method
=
\
count
(
$
segments
)
===
2
$
segments
[
1
]
:
'sanitize'
;
// Return the constructed callback.
return
[
$
this
->
container
->
get
(
$
segments
[
0
]
)
,
$
method
]
;
}

Resolve a callback from a class and method pair.

@param string $callback

@return array<object, string>

Resolve a callback from a class and method pair .


public function resolve(string $expression, $callable, array $aliases = []): StringCommand
    {
        $this->assertCallableIsValid($callable);

        $commandFunction = function (InputInterface $input, OutputInterface $output) use ($callable) {
            $parameters = \array_merge(
                [
                    // Injection by parameter name
                    'input'  => $input,
                    'output' => $output,
                    // Injections by type-hint
                    InputInterface::class  => $input,
                    OutputInterface::class => $output,
                    Input::class           => $input,
                    Output::class          => $output,
                    SymfonyStyle::class    => new SymfonyStyle($input, $output),
                ],
                $input->getArguments(),
                $input->getOptions()
            );

            if ($callable instanceof Closure) {
                $callable = $callable->bindTo($this->console, $this->console);
            }

            try {
                return $this->invoker->addResolver(new HyphenatedInputResolver())->call($callable, $parameters);
            } catch (InvokerInvocationException $exception) {
                throw new InvocationException(
                    \sprintf(
                        "Impossible to call the '%s' command: %s",
                        $input->getFirstArgument(),
                        $exception->getMessage()
                    ),
                    0,
                    $exception
                );
            }
        };

        $command = self::createCommand($expression, $commandFunction);
        $command->setAliases($aliases);
        $command->defaults($this->defaultsViaReflection($command, $callable));

        return $command;
    }

Resolve a command from expression.

@param string                $expression Defines the arguments and options of the command
@param array|callable|string $callable   Called when the command is called.
When using a container, this can be a "pseudo-callable"
i.e. the name of the container entry to invoke.
@param array                 $aliases    an array of aliases for the command

@throws \Viserio\Component\Contract\Console\Exception\InvocationException
@throws \Viserio\Component\Contract\Console\Exception\InvalidArgumentException

@return \Viserio\Component\Console\Command\StringCommand


private static function createCommand(string $expression, callable $callable): StringCommand
    {
        $result = ExpressionParser::parse($expression);

        $command = new StringCommand($result['name']);
        $command->getDefinition()->addArguments($result['arguments']);
        $command->getDefinition()->addOptions($result['options']);
        $command->setCode($callable);

        return $command;
    }

private static function createCommand ( string $ expression , callable $ callable ) : StringCommand { $ result = ExpressionParser :: parse ( $ expression ) ; $ command = new StringCommand ( $ result [ 'name' ] ) ; $ command -> getDefinition ( ) -> addArguments ( $ result [ 'arguments' ] ) ; $ command -> getDefinition ( ) -> addOptions ( $ result [ 'options' ] ) ; $ command -> setCode ( $ callable ) ; return $ command ; }

Create a new command.

@param string   $expression
@param callable $callable

@throws \Symfony\Component\Console\Exception\LogicException
@throws \Symfony\Component\Console\Exception\InvalidArgumentException
@throws \Viserio\Component\Contract\Console\Exception\InvalidCommandExpression

@return \Viserio\Component\Console\Command\StringCommand


private function defaultsViaReflection(StringCommand $command, $callable): array
    {
        if (! \is_callable($callable)) {
            return [];
        }

        $function   = CallableReflection::create($callable);
        $definition = $command->getDefinition();
        $defaults   = [];

        foreach ($function->getParameters() as $parameter) {
            if (! $parameter->isDefaultValueAvailable()) {
                continue;
            }

            $parameterName      = $parameter->name;
            $hyphenatedCaseName = Str::snake($parameterName, '-');

            if ($definition->hasArgument($hyphenatedCaseName) || $definition->hasOption($hyphenatedCaseName)) {
                $parameterName = $hyphenatedCaseName;
            }

            if (! $definition->hasArgument($parameterName) && ! $definition->hasOption($parameterName)) {
                continue;
            }

            $defaults[$parameterName] = $parameter->getDefaultValue();
        }

        return $defaults;
    }

private function defaultsViaReflection ( StringCommand $ command , $ callable ) : array { if ( ! \ is_callable ( $ callable ) ) { return [ ] ; } $ function = CallableReflection :: create ( $ callable ) ; $ definition = $ command -> getDefinition ( ) ; $ defaults = [ ] ; foreach ( $ function -> getParameters ( ) as $ parameter ) { if ( ! $ parameter -> isDefaultValueAvailable ( ) ) { continue ; } $ parameterName = $ parameter -> name ; $ hyphenatedCaseName = Str :: snake ( $ parameterName , '-' ) ; if ( $ definition -> hasArgument ( $ hyphenatedCaseName ) || $ definition -> hasOption ( $ hyphenatedCaseName ) ) { $ parameterName = $ hyphenatedCaseName ; } if ( ! $ definition -> hasArgument ( $ parameterName ) && ! $ definition -> hasOption ( $ parameterName ) ) { continue ; } $ defaults [ $ parameterName ] = $ parameter -> getDefaultValue ( ) ; } return $ defaults ; }

Reflect default values from callable.

@param \Viserio\Component\Console\Command\StringCommand $command
@param callable|string                                  $callable

@throws \Invoker\Exception\NotCallableException

@return array


private function assertCallableIsValid($callable): void
    {
        try {
            $this->console->getContainer();
        } catch (LogicException $e) {
            if ($this->isStaticCallToNonStaticMethod($callable)) {
                [$class, $method] = $callable;

                $message = "['{$class}', '{$method}'] is not a callable because '{$method}' is a static method.";
                $message .= " Either use [new {$class}(), '{$method}'] or configure a dependency injection container that supports autowiring.";

                throw new InvalidArgumentException($message);
            }
        }
    }

Check if callable is valid.

@param mixed $callable

@throws \ReflectionException
@throws \Viserio\Component\Contract\Console\Exception\InvalidArgumentException

@return void


private function isStaticCallToNonStaticMethod($callable): bool
    {
        if (\is_array($callable) && \is_string($callable[0])) {
            [$class, $method] = $callable;

            $reflection = new ReflectionMethod($class, $method);

            return ! $reflection->isStatic();
        }

        return false;
    }

private function isStaticCallToNonStaticMethod ( $ callable ) : bool { if ( \ is_array ( $ callable ) && \ is_string ( $ callable [ 0 ] ) ) { [ $ class , $ method ] = $ callable ; $ reflection = new ReflectionMethod ( $ class , $ method ) ; return ! $ reflection -> isStatic ( ) ; } return false ; }

Check if the callable represents a static call to a non-static method.

@param mixed $callable

@throws \ReflectionException

@return bool

Check if the callable represents a static call to a non - static method .


public static function createCookieJar(ContainerInterface $container): JarContract
    {
        $options = self::resolveOptions($container->get('config'));

        return (new CookieJar())->setDefaultPathAndDomain(
            $options['path'],
            $options['domain'],
            $options['secure']
        );
    }

public static function createCookieJar ( ContainerInterface $ container ) : JarContract { $ options = self :: resolveOptions ( $ container -> get ( 'config' ) ) ; return ( new CookieJar ( ) ) -> setDefaultPathAndDomain ( $ options [ 'path' ] , $ options [ 'domain' ] , $ options [ 'secure' ] ) ; }

Create a new CookieJar instance.

@param \Psr\Container\ContainerInterface $container

@return \Viserio\Component\Contract\Cookie\QueueingFactory


private function convertElement(DOMDocument $document, $element, $value): void
    {
        $sequential = self::isArrayAllKeySequential($value);

        if (! \is_array($value)) {
            $element->nodeValue = \htmlspecialchars((string) $value);

            return;
        }

        foreach ($value as $key => $data) {
            if (! $sequential) {
                if (($key === '_attributes') || ($key === '@attributes')) {
                    foreach ($data as $attrKey => $attrVal) {
                        $element->setAttribute($attrKey, (string) $attrVal);
                    }
                } elseif ((($key === '_value') || ($key === '@value')) && \is_string($data)) {
                    $element->nodeValue = \htmlspecialchars($data);
                } elseif ((($key === '_cdata') || ($key === '@cdata')) && \is_string($data)) {
                    $element->appendChild($document->createCDATASection($data));
                } else {
                    if (! \is_string($key)) {
                        throw new DOMException('Invalid Character Error.');
                    }

                    $this->addNode($document, $element, $key, $data);
                }
            } elseif (\is_array($data)) {
                $this->addCollectionNode($document, $element, $data);
            } else {
                $this->addSequentialNode($element, $data);
            }
        }
    }

private
function
convertElement
(
DOMDocument
$
document
,
$
element
,
$
value
)
:
void
{
$
sequential
=
self
::
isArrayAllKeySequential
(
$
value
)
;
if
(
!
\
is_array
(
$
value
)
)
{
$
element
->
nodeValue
=
\
htmlspecialchars
(
(
string
)
$
value
)
;
return
;
}
foreach
(
$
value
as
$
key
=>
$
data
)
{
if
(
!
$
sequential
)
{
if
(
(
$
key
===
'_attributes'
)
||
(
$
key
===
'@attributes'
)
)
{
foreach
(
$
data
as
$
attrKey
=>
$
attrVal
)
{
$
element
->
setAttribute
(
$
attrKey
,
(
string
)
$
attrVal
)
;
}
}
elseif
(
(
(
$
key
===
'_value'
)
||
(
$
key
===
'@value'
)
)
&&
\
is_string
(
$
data
)
)
{
$
element
->
nodeValue
=
\
htmlspecialchars
(
$
data
)
;
}
elseif
(
(
(
$
key
===
'_cdata'
)
||
(
$
key
===
'@cdata'
)
)
&&
\
is_string
(
$
data
)
)
{
$
element
->
appendChild
(
$
document
->
createCDATASection
(
$
data
)
)
;
}
else
{
if
(
!
\
is_string
(
$
key
)
)
{
throw
new
DOMException
(
'Invalid Character Error.'
)
;
}
$
this
->
addNode
(
$
document
,
$
element
,
$
key
,
$
data
)
;
}
}
elseif
(
\
is_array
(
$
data
)
)
{
$
this
->
addCollectionNode
(
$
document
,
$
element
,
$
data
)
;
}
else
{
$
this
->
addSequentialNode
(
$
element
,
$
data
)
;
}
}
}

Parse individual element.

@param \DOMDocument         $document
@param \DOMElement|\DOMNode $element
@param array|string         $value

@throws \DOMException

@return void


private function addNode(DOMDocument $document, $element, string $key, $value): void
    {
        $key = \str_replace(' ', '_', $key);

        $child = $document->createElement($key);

        $element->appendChild($child);

        $this->convertElement($document, $child, $value);
    }

private
function
addNode
(
DOMDocument
$
document
,
$
element
,
string
$
key
,
$
value
)
:
void
{
$
key
=
\
str_replace
(
' '
,
'_'
,
$
key
)
;
$
child
=
$
document
->
createElement
(
$
key
)
;
$
element
->
appendChild
(
$
child
)
;
$
this
->
convertElement
(
$
document
,
$
child
,
$
value
)
;
}

Add node.

@param \DOMDocument         $document
@param \DOMElement|\DOMNode $element
@param string               $key
@param string|string[]      $value

@throws \DOMException

@return void


private function addCollectionNode(DOMDocument $document, $element, $value): void
    {
        if ($element->childNodes->length === 0 && $element->attributes->length === 0) {
            $this->convertElement($document, $element, $value);
        }

        $child = $element->cloneNode();

        $element->parentNode->appendChild($child);

        $this->convertElement($document, $child, $value);
    }

private function addCollectionNode ( DOMDocument $ document , $ element , $ value ) : void { if ( $ element -> childNodes -> length === 0 && $ element -> attributes -> length === 0 ) { $ this -> convertElement ( $ document , $ element , $ value ) ; } $ child = $ element -> cloneNode ( ) ; $ element -> parentNode -> appendChild ( $ child ) ; $ this -> convertElement ( $ document , $ child , $ value ) ; }

Add collection node.

@param \DOMDocument         $document
@param \DOMElement|\DOMNode $element
@param string|string[]      $value

@throws \DOMException

@return void


private function createRootElement(DOMDocument $document, $rootElement): DOMElement
    {
        if (\is_string($rootElement)) {
            return $document->createElement($rootElement ?: 'root');
        }

        $rootElementName = $rootElement['rootElementName'] ?? 'root';
        $element         = $document->createElement($rootElementName);

        foreach ($rootElement as $key => $value) {
            if ($key !== '_attributes' && $key !== '@attributes') {
                continue;
            }

            foreach ($rootElement[$key] as $attrKey => $attrVal) {
                $element->setAttribute($attrKey, $attrVal);
            }
        }

        return $element;
    }

private function createRootElement ( DOMDocument $ document , $ rootElement ) : DOMElement { if ( \ is_string ( $ rootElement ) ) { return $ document -> createElement ( $ rootElement ? : 'root' ) ; } $ rootElementName = $ rootElement [ 'rootElementName' ] ?? 'root' ; $ element = $ document -> createElement ( $ rootElementName ) ; foreach ( $ rootElement as $ key => $ value ) { if ( $ key !== '_attributes' && $ key !== '@attributes' ) { continue ; } foreach ( $ rootElement [ $ key ] as $ attrKey => $ attrVal ) { $ element -> setAttribute ( $ attrKey , $ attrVal ) ; } } return $ element ; }

Create the root element.

@param \DOMDocument $document
@param array|string $rootElement

@return \DOMElement