protected function decimalValue()
    {
        $base = $this->numberSystem->getBase();
        $result = 0;

        foreach (array_reverse($this->getDigits()) as $position => $value) {
            $numberSystemPosition = $this->numberSystem->getSymbolPosition($value);
            $result += $numberSystemPosition * pow($base, $position);
        }

        return $result;
    }

protected function decimalValue ( ) { $ base = $ this -> numberSystem -> getBase ( ) ; $ result = 0 ; foreach ( array_reverse ( $ this -> getDigits ( ) ) as $ position => $ value ) { $ numberSystemPosition = $ this -> numberSystem -> getSymbolPosition ( $ value ) ; $ result += $ numberSystemPosition * pow ( $ base , $ position ) ; } return $ result ; }

We use this to convert every number to decimal for calculations.

We use this to convert every number to decimal for calculations .


public function add(Number $addend)
    {
        $resultDecimalValue = $this->decimalValue() + $addend->decimalValue();

        $result = new Number($resultDecimalValue);

        return $result->convert($this->getNumberSystem());
    }

public function add ( Number $ addend ) { $ resultDecimalValue = $ this -> decimalValue ( ) + $ addend -> decimalValue ( ) ; $ result = new Number ( $ resultDecimalValue ) ; return $ result -> convert ( $ this -> getNumberSystem ( ) ) ; }

Add two number together.
The number-system of the result will be the one of the number
who's was the called object.

@param Number|Number $addend

@return Number

Add two number together . The number - system of the result will be the one of the number who s was the called object .


public function subtract(Number $subtractor)
    {
        $resultDecimalValue = $this->decimalValue() - $subtractor->decimalValue();

        $result = new Number($resultDecimalValue);

        return $result->convert($this->getNumberSystem());
    }

public function subtract ( Number $ subtractor ) { $ resultDecimalValue = $ this -> decimalValue ( ) - $ subtractor -> decimalValue ( ) ; $ result = new Number ( $ resultDecimalValue ) ; return $ result -> convert ( $ this -> getNumberSystem ( ) ) ; }

Subtract two numbers.
The number-system of the result will be the one of the number
who's was the called object.

@param Number $subtractor

@return Number

Subtract two numbers . The number - system of the result will be the one of the number who s was the called object .


public function multiply(Number $multiplicator)
    {
        $resultDecimalValue = $this->decimalValue() * $multiplicator->decimalValue();

        $result = new Number($resultDecimalValue);

        return $result->convert($this->getNumberSystem());
    }

public function multiply ( Number $ multiplicator ) { $ resultDecimalValue = $ this -> decimalValue ( ) * $ multiplicator -> decimalValue ( ) ; $ result = new Number ( $ resultDecimalValue ) ; return $ result -> convert ( $ this -> getNumberSystem ( ) ) ; }

Multiply two numbers.
The number-system of the result will be the one of the number
who's was the called object.

@param Number $multiplicator

@return Number

Multiply two numbers . The number - system of the result will be the one of the number who s was the called object .


public function divide(Number $multiplicator)
    {
        $resultDecimalValue = round($this->decimalValue() / $multiplicator->decimalValue(), 0);

        $result = new Number($resultDecimalValue);

        return $result->convert($this->getNumberSystem());
    }

public function divide ( Number $ multiplicator ) { $ resultDecimalValue = round ( $ this -> decimalValue ( ) / $ multiplicator -> decimalValue ( ) , 0 ) ; $ result = new Number ( $ resultDecimalValue ) ; return $ result -> convert ( $ this -> getNumberSystem ( ) ) ; }

Divide two numbers.
The number-system of the result will be the one of the number
who's was the called object.

@param Number $multiplicator

@return Number

Divide two numbers . The number - system of the result will be the one of the number who s was the called object .


public static function getAdapter(\Mysqli $mysqli)
    {
        $driver = new Driver\Mysqli\Mysqli($mysqli);
        $adapter = new Adapter($driver);
        return $adapter;
    }

public static function getAdapter ( \ Mysqli $ mysqli ) { $ driver = new Driver \ Mysqli \ Mysqli ( $ mysqli ) ; $ adapter = new Adapter ( $ driver ) ; return $ adapter ; }

Return a Zend\Db\Adapter\Adapter object from an existing mysqli connection
@param \Mysqli $mysqli
@return Adapter

Return a Zend \ Db \ Adapter \ Adapter object from an existing mysqli connection


public static function aliasList()
    {
        $result = [];
        foreach (\Yii::$aliases as $alias => $data) {
            if (is_array($data)) {
                $result = array_merge($result, array_keys($data));
            } else {
                $result[] = $alias;
            }
        }
        asort($result);
        return array_values($result);
    }

public static function aliasList ( ) { $ result = [ ] ; foreach ( \ Yii :: $ aliases as $ alias => $ data ) { if ( is_array ( $ data ) ) { $ result = array_merge ( $ result , array_keys ( $ data ) ) ; } else { $ result [ ] = $ alias ; } } asort ( $ result ) ; return array_values ( $ result ) ; }

System path aliases list.
@return array available alias list.


public static function findAliases($query)
    {
        $query = '@' . str_replace('@', '', $query);
        $pattern = '/' . preg_quote($query, '/') . '/';
        return preg_grep($pattern, self::aliasList());
    }

public static function findAliases ( $ query ) { $ query = '@' . str_replace ( '@' , '' , $ query ) ; $ pattern = '/' . preg_quote ( $ query , '/' ) . '/' ; return preg_grep ( $ pattern , self :: aliasList ( ) ) ; }

Searches all path aliases.
@param string $query search string started with @
@return array found system path aliases matching search query.


private function replace()
    {
        $destination = Yii::getAlias($this->destination);
        $destinationModuleName = $this->getDestinationModuleName();
        foreach (FileHelper::findFiles($destination) as $path) {
            if (!$this->replace && in_array($path, $this->keepFiles)) {
                continue;
            }
            if (!preg_match('/^.*\.php$/', $path, $matches)) { // php file.
                continue;
            } else if (preg_match('/^.*\W([A-Z]\w+)\.php$/', $path, $matches)) { // Class file.
                file_put_contents($path, $this->createClassContent($matches[1], $path));
            } else if (self::isMigration($path)) { // Class file.
                file_put_contents($path, $this->updateFileContent($path));
                if ($destinationModuleName) {
                    $this->renameClassFile($path, function($className) use ($destinationModuleName){
                        return $className . '_' . $destinationModuleName;
                    });
                }
            } else if ($this->inheritContent) {
                file_put_contents($path, $this->createFileContent($path));
            } else {
                file_put_contents($path, $this->updateFileContent($path));
            }
        }
        return true;
    }

private
function
replace
(
)
{
$
destination
=
Yii
::
getAlias
(
$
this
->
destination
)
;
$
destinationModuleName
=
$
this
->
getDestinationModuleName
(
)
;
foreach
(
FileHelper
::
findFiles
(
$
destination
)
as
$
path
)
{
if
(
!
$
this
->
replace
&&
in_array
(
$
path
,
$
this
->
keepFiles
)
)
{
continue
;
}
if
(
!
preg_match
(
'/^.*\.php$/'
,
$
path
,
$
matches
)
)
{
// php file.
continue
;
}
else
if
(
preg_match
(
'/^.*\W([A-Z]\w+)\.php$/'
,
$
path
,
$
matches
)
)
{
// Class file.
file_put_contents
(
$
path
,
$
this
->
createClassContent
(
$
matches
[
1
]
,
$
path
)
)
;
}
else
if
(
self
::
isMigration
(
$
path
)
)
{
// Class file.
file_put_contents
(
$
path
,
$
this
->
updateFileContent
(
$
path
)
)
;
if
(
$
destinationModuleName
)
{
$
this
->
renameClassFile
(
$
path
,
function
(
$
className
)
use
(
$
destinationModuleName
)
{
return
$
className
.
'_'
.
$
destinationModuleName
;
}
)
;
}
}
else
if
(
$
this
->
inheritContent
)
{
file_put_contents
(
$
path
,
$
this
->
createFileContent
(
$
path
)
)
;
}
else
{
file_put_contents
(
$
path
,
$
this
->
updateFileContent
(
$
path
)
)
;
}
}
return
true
;
}

Replaces all new module classes content with empty template.
@return boolean

Replaces all new module classes content with empty template .


public function readLine($bufferSize, $localTimeout = null)
    {
        $line = '';
        while (!feof($this->socket)) {
            if (null !== $localTimeout) {
                stream_set_timeout($this->socket, $localTimeout);
            } elseif ($this->deadline) {
                stream_set_timeout($this->socket, max($this->deadline - time(), 1));
            }

            $line .= @fgets($this->socket, $bufferSize);

            if (null === $localTimeout) {
                $this->checkTimeout();

            } else {
                $info = stream_get_meta_data($this->socket);
                // reset socket timeout if we don't have request timeout specified,
                // prevents further calls failing with a bogus Exception
                if (!$this->deadline) {
                    $default = (int)@ini_get('default_socket_timeout');
                    stream_set_timeout($this->socket, $default > 0 ? $default : PHP_INT_MAX);
                }
                if ($info['timed_out']) {
                    throw new HTTP_Request2_MessageException(
                        "readLine() call timed out", HTTP_Request2_Exception::TIMEOUT
                    );
                }
            }
            if (substr($line, -1) == "\n") {
                return rtrim($line, "\r\n");
            }
        }
        return $line;
    }

Reads until either the end of the socket or a newline, whichever comes first

Strips the trailing newline from the returned data, handles global
request timeout. Method idea borrowed from Net_Socket PEAR package.

@param int $bufferSize   buffer size to use for reading
@param int $localTimeout timeout value to use just for this call
(used when waiting for "100 Continue" response)

@return   string Available data up to the newline (not including newline)
@throws   HTTP_Request2_MessageException     In case of timeout

Reads until either the end of the socket or a newline whichever comes first


public function enableCrypto()
    {
        $modes = array(
            STREAM_CRYPTO_METHOD_TLS_CLIENT,
            STREAM_CRYPTO_METHOD_SSLv3_CLIENT,
            STREAM_CRYPTO_METHOD_SSLv23_CLIENT,
            STREAM_CRYPTO_METHOD_SSLv2_CLIENT
        );

        foreach ($modes as $mode) {
            if (stream_socket_enable_crypto($this->socket, true, $mode)) {
                return;
            }
        }
        throw new HTTP_Request2_ConnectionException(
            'Failed to enable secure connection when connecting through proxy'
        );
    }

Turns on encryption on a socket

@throws HTTP_Request2_ConnectionException


protected function checkTimeout()
    {
        $info = stream_get_meta_data($this->socket);
        if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {
            $reason = $this->deadline
                ? "after {$this->timeout} second(s)"
                : 'due to default_socket_timeout php.ini setting';
            throw new HTTP_Request2_MessageException(
                "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT
            );
        }
    }

Throws an Exception if stream timed out

@throws HTTP_Request2_MessageException


public function addRoute(RouteInterface $route) {
        if (!$route->isValid()) {
            //perhaps some log?
            return;
        }

        $routeValue = $route->getAction()->getValue();
        $this->app->map(
            [strtolower($route->getMethod()->getValue())],
            $route->getUri()->getValue(),
            function (
                RequestInterface $request,
                ResponseInterface $response,
                $params
            ) use ($routeValue) {
                $handler = $this->get($routeValue);
                return $handler->execute($request, $response, $params);
            }
        );
    }

public
function
addRoute
(
RouteInterface
$
route
)
{
if
(
!
$
route
->
isValid
(
)
)
{
//perhaps some log?
return
;
}
$
routeValue
=
$
route
->
getAction
(
)
->
getValue
(
)
;
$
this
->
app
->
map
(
[
strtolower
(
$
route
->
getMethod
(
)
->
getValue
(
)
)
]
,
$
route
->
getUri
(
)
->
getValue
(
)
,
function
(
RequestInterface
$
request
,
ResponseInterface
$
response
,
$
params
)
use
(
$
routeValue
)
{
$
handler
=
$
this
->
get
(
$
routeValue
)
;
return
$
handler
->
execute
(
$
request
,
$
response
,
$
params
)
;
}
)
;
}

Register a new route with the given verbs.

@param  string  $methods
@param  string  $uri
@param  \Closure|array|string  $action
@return void

Register a new route with the given verbs .


private function setItems(array $items)
    {
        $this->items = array_merge($this->defaults, $items);

        $this->checkAttributes();

        return $this;
    }

private function setItems ( array $ items ) { $ this -> items = array_merge ( $ this -> defaults , $ items ) ; $ this -> checkAttributes ( ) ; return $ this ; }

Set items.

@param  array  $items

@return self


public function build($siteKey, array $items = [])
    {
        $this->setItems($items);

        $output = [];

        foreach ($this->getItems($siteKey) as $key => $value) {
            $output[] = trim($key) . '="' . trim($value) . '"';
        }

        return implode(' ', $output);
    }

public
function
build
(
$
siteKey
,
array
$
items
=
[
]
)
{
$
this
->
setItems
(
$
items
)
;
$
output
=
[
]
;
foreach
(
$
this
->
getItems
(
$
siteKey
)
as
$
key
=>
$
value
)
{
$
output
[
]
=
trim
(
$
key
)
.
'="'
.
trim
(
$
value
)
.
'"'
;
}
return
implode
(
' '
,
$
output
)
;
}

Build attributes.

@param  string  $siteKey
@param  array   $items

@return string


public function prepareNameAttribute($name)
    {
        if (is_null($name)) return [];

        if ($name === NoCaptcha::CAPTCHA_NAME) {
            throw new InvalidArgumentException(
                'The captcha name must be different from "' . NoCaptcha::CAPTCHA_NAME . '".'
            );
        }

        return array_combine(['id', 'name'], [$name, $name]);
    }

Prepare the name and id attributes.

@param  string|null  $name

@return array

@throws \Arcanedev\NoCaptcha\Exceptions\InvalidArgumentException


private function checkDataAttribute($name, $default, array $available)
    {
        $item = $this->getItem($name);

        if ( ! is_null($item)) {
            $item = (is_string($item) and in_array($item, $available))
                ? strtolower(trim($item))
                : $default;

            $this->setItem($name, $item);
        }
    }

private function checkDataAttribute ( $ name , $ default , array $ available ) { $ item = $ this -> getItem ( $ name ) ; if ( ! is_null ( $ item ) ) { $ item = ( is_string ( $ item ) and in_array ( $ item , $ available ) ) ? strtolower ( trim ( $ item ) ) : $ default ; $ this -> setItem ( $ name , $ item ) ; } }

Check data Attribute.

@param  string  $name
@param  string  $default
@param  array   $available


public function add($resource)
    {
        if (!isset($this->added[$path = $resource->getPath()])) {
            $this->queue->add($resource);
            $this->added[$path] = true;
        }
    }

public function add ( $ resource ) { if ( ! isset ( $ this -> added [ $ path = $ resource -> getPath ( ) ] ) ) { $ this -> queue -> add ( $ resource ) ; $ this -> added [ $ path ] = true ; } }

Adds a resource to the queue.

@param \Orbt\ResourceMirror\Resource\Resource $resource


public static function fromArray($dayOfWeek, array $openingIntervals): Day
    {
        $intervals = [];
        foreach ($openingIntervals as $interval) {
            if ($interval instanceof TimeIntervalInterface) {
                $intervals[] = $interval;
            } elseif (\is_array($intervals)) {
                $intervals[] = new TimeInterval(
                    TimeBuilder::fromString($interval[0]),
                    TimeBuilder::fromString($interval[1])
                );
            }
        }

        $day = new Day($dayOfWeek, $intervals);
        $dayIntervals = $day->getOpeningHoursIntervals();
        /** @var TimeIntervalInterface $dayInterval */
        $dayInterval = \reset($dayIntervals);
        if (self::isIntervalAllDay($dayInterval->getStart(), $dayInterval->getEnd())) {
            return new AllDay($dayOfWeek);
        }

        return $day;
    }

Create a new Day.

@param integer $dayOfWeek The day of week.
@param array $openingIntervals The opening intervals.
@return Day


public static function fromAssociativeArray(array $data): DayInterface
    {
        if (!isset($data['openingIntervals'], $data['dayOfWeek']) || !\is_array($data['openingIntervals'])) {
            throw new \InvalidArgumentException('Array is not valid.');
        }

        $openingIntervals = [];
        foreach ($data['openingIntervals'] as $openingInterval) {
            if (!isset($openingInterval['start'], $openingInterval['end'])) {
                throw new \InvalidArgumentException('Array is not valid.');
            }
            $start = TimeBuilder::fromArray($openingInterval['start']);
            $end = TimeBuilder::fromArray($openingInterval['end']);
            if (self::isIntervalAllDay($start, $end)) {
                return new AllDay($data['dayOfWeek']);
            }

            $openingIntervals[] = new TimeInterval($start, $end);
        }

        return new Day($data['dayOfWeek'], $openingIntervals);
    }

public
static
function
fromAssociativeArray
(
array
$
data
)
:
DayInterface
{
if
(
!
isset
(
$
data
[
'openingIntervals'
]
,
$
data
[
'dayOfWeek'
]
)
||
!
\
is_array
(
$
data
[
'openingIntervals'
]
)
)
{
throw
new
\
InvalidArgumentException
(
'Array is not valid.'
)
;
}
$
openingIntervals
=
[
]
;
foreach
(
$
data
[
'openingIntervals'
]
as
$
openingInterval
)
{
if
(
!
isset
(
$
openingInterval
[
'start'
]
,
$
openingInterval
[
'end'
]
)
)
{
throw
new
\
InvalidArgumentException
(
'Array is not valid.'
)
;
}
$
start
=
TimeBuilder
::
fromArray
(
$
openingInterval
[
'start'
]
)
;
$
end
=
TimeBuilder
::
fromArray
(
$
openingInterval
[
'end'
]
)
;
if
(
self
::
isIntervalAllDay
(
$
start
,
$
end
)
)
{
return
new
AllDay
(
$
data
[
'dayOfWeek'
]
)
;
}
$
openingIntervals
[
]
=
new
TimeInterval
(
$
start
,
$
end
)
;
}
return
new
Day
(
$
data
[
'dayOfWeek'
]
,
$
openingIntervals
)
;
}

Create a DayInterface object from an array.

@param array $data The day data.
@return DayInterface

Create a DayInterface object from an array .


private static function isIntervalAllDay(Time $start, Time $end): bool
    {
        if ($start->getHours() !== 0 || $start->getMinutes() !== 0 || $start->getSeconds() !== 0) {
            return false;
        }

        if ($end->getHours() !== 24 || $end->getMinutes() !== 0 || $end->getSeconds() !== 0) {
            return false;
        }

        return true;
    }

private static function isIntervalAllDay ( Time $ start , Time $ end ) : bool { if ( $ start -> getHours ( ) !== 0 || $ start -> getMinutes ( ) !== 0 || $ start -> getSeconds ( ) !== 0 ) { return false ; } if ( $ end -> getHours ( ) !== 24 || $ end -> getMinutes ( ) !== 0 || $ end -> getSeconds ( ) !== 0 ) { return false ; } return true ; }

Check if an interval array is all day.

@param Time $start The start time.
@param Time $end The end time.
@return boolean


public static function fromArray(Array $data)
    {
        $request = new static();

        if (!isset($data['body']) || !isset($data['request'])) {
            throw new UnexpectedValueException(
                'Unexpected data, invalid data'
            );
        }

        $body = $data['body'];
        $params = $data['request'];

        $request->setTimestamp(microtime(true));

        if (isset($params['RequestURI'])) {
            $request->setRequestUrl($params['RequestURI']);
        }

        if (isset($params['Method'])) {
            $request->setRequestMethod($params['Method']);
        }

        if (isset($params['Header']) && is_array($params['Header'])) {
            $headers = $params['Header'];

            if (isset($params['Host'])) {
                $headers['Host'] = [$params['Host']];
            }

            $request->setHeaders($headers);

            //Malformed cookies will return a fatal error
            $cookies = $cookies = new Cookie($request->getHeader('Cookie'));
            if ($cookies) {
                $request->setCookies($cookies);
            }
        }

        if (isset($params['URL']['RawQuery'])) {
            parse_str($params['URL']['RawQuery'], $queryFields);
            $request->setQueryFields($queryFields);
        }

        if (isset($params['Host']) && isset($params['Proto'])) {
            $info = parse_url($params['Host']);
            $info['proto'] = $params['Proto'];

            $request->setServerInfo($info);
        }

        if (isset($params['RemoteAddr'])) {
            $info = parse_url($params['RemoteAddr']);
            $request->setRemoteInfo($info);
        }

        if (strlen($body)) {
            parse_str($body, $postFields);
            $request->setPostFields($postFields);
        }

        return $request;
    }

Configure the request based on a JSON, usually received on the workload
from a GearmanJob from the nginx.

@param  string  $json
@return boolean

Configure the request based on a JSON usually received on the workload from a GearmanJob from the nginx .


public function setServerInfo(array $info)
    {
        $this->server = $info;

        if (isset($info['name']) && $info['name']) $name = (string) $info['name'];
        else $name = sprintf('%s:%s', $info['host'], $info['port']);

        $this->setServerGlobal('SERVER_NAME', $name);

        $this->setServerGlobal('SERVER_ADDR', (string) $info['host']);
        $this->setServerGlobal('SERVER_PORT', (string) $info['port']);
        $this->setServerGlobal('SERVER_PROTOCOL', (string) $info['proto']);

        //TODO: Version Server
        $this->setServerGlobal('SERVER_SOFTWARE', 'Skeetr/0.0.2');
    }

public
function
setServerInfo
(
array
$
info
)
{
$
this
->
server
=
$
info
;
if
(
isset
(
$
info
[
'name'
]
)
&&
$
info
[
'name'
]
)
$
name
=
(
string
)
$
info
[
'name'
]
;
else
$
name
=
sprintf
(
'%s:%s'
,
$
info
[
'host'
]
,
$
info
[
'port'
]
)
;
$
this
->
setServerGlobal
(
'SERVER_NAME'
,
$
name
)
;
$
this
->
setServerGlobal
(
'SERVER_ADDR'
,
(
string
)
$
info
[
'host'
]
)
;
$
this
->
setServerGlobal
(
'SERVER_PORT'
,
(
string
)
$
info
[
'port'
]
)
;
$
this
->
setServerGlobal
(
'SERVER_PROTOCOL'
,
(
string
)
$
info
[
'proto'
]
)
;
//TODO: Version Server
$
this
->
setServerGlobal
(
'SERVER_SOFTWARE'
,
'Skeetr/0.0.2'
)
;
}

Sets the server info

@param string $info mandatory keys: name, addr, port and proto


public function setHeaders(array $headers)
    {
        parent::addHeaders($headers);

        $this->setServerGlobal('HTTP_HOST', (string) $this->getHeader('Host')[0]);
        $this->setServerGlobal('HTTP_ACCEPT', (string) $this->getHeader('Accept')[0]);
        $this->setServerGlobal('HTTP_CONNECTION', (string) $this->getHeader('Connection')[0]);
        $this->setServerGlobal('HTTP_USER_AGENT', (string) $this->getHeader('User-Agent')[0]);
        $this->setServerGlobal('HTTP_ACCEPT_ENCODING', (string) $this->getHeader('Accept-Encoding')[0]);
        $this->setServerGlobal('HTTP_ACCEPT_LANGUAGE', (string) $this->getHeader('Accept-Language')[0]);
        $this->setServerGlobal('HTTP_ACCEPT_CHARSET', (string) $this->getHeader('Accept-Charset')[0]);
        $this->setServerGlobal('HTTP_CACHE_CONTROL', (string) $this->getHeader('Cache-Control')[0]);
        $this->setServerGlobal('HTTP_COOKIE', (string) $this->getHeader('Cookie')[0]);
    }

public function setHeaders ( array $ headers ) { parent :: addHeaders ( $ headers ) ; $ this -> setServerGlobal ( 'HTTP_HOST' , ( string ) $ this -> getHeader ( 'Host' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_ACCEPT' , ( string ) $ this -> getHeader ( 'Accept' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_CONNECTION' , ( string ) $ this -> getHeader ( 'Connection' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_USER_AGENT' , ( string ) $ this -> getHeader ( 'User-Agent' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_ACCEPT_ENCODING' , ( string ) $ this -> getHeader ( 'Accept-Encoding' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_ACCEPT_LANGUAGE' , ( string ) $ this -> getHeader ( 'Accept-Language' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_ACCEPT_CHARSET' , ( string ) $ this -> getHeader ( 'Accept-Charset' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_CACHE_CONTROL' , ( string ) $ this -> getHeader ( 'Cache-Control' ) [ 0 ] ) ; $ this -> setServerGlobal ( 'HTTP_COOKIE' , ( string ) $ this -> getHeader ( 'Cookie' ) [ 0 ] ) ; }

Sets the headers.

@param array $headers associative array containing the new HTTP headers


public function setPostFields(array $fields)
    {
        $this->post = $fields;

        $body = new Message\Body();
        $body->append(http_build_query($fields));
        parent::setBody($body);

        $_POST = $fields;
        $_REQUEST = array_merge($_GET, $_POST);
    }

public function setPostFields ( array $ fields ) { $ this -> post = $ fields ; $ body = new Message \ Body ( ) ; $ body -> append ( http_build_query ( $ fields ) ) ; parent :: setBody ( $ body ) ; $ _POST = $ fields ; $ _REQUEST = array_merge ( $ _GET , $ _POST ) ; }


public function setQueryFields(array $fields)
    {
        $this->get = $fields;

        $this->setServerGlobal('QUERY_STRING', $this->getQueryData());

        $_GET = $fields;
        $_REQUEST = array_merge($_GET, $_POST);
    }

public function setQueryFields ( array $ fields ) { $ this -> get = $ fields ; $ this -> setServerGlobal ( 'QUERY_STRING' , $ this -> getQueryData ( ) ) ; $ _GET = $ fields ; $ _REQUEST = array_merge ( $ _GET , $ _POST ) ; }


public function getHeader($header, $into_class = null)
    {
        $header = parent::getHeader($header);

        if (!is_array($header)) {
            return [$header];
        }

        return $header;
    }

public function getHeader ( $ header , $ into_class = null ) { $ header = parent :: getHeader ( $ header ) ; if ( ! is_array ( $ header ) ) { return [ $ header ] ; } return $ header ; }

Get a header by name

@param  string $header
@return string


public function toArray()
    {
        return array(
            'url' => $this->getRequestUrl(),
            'method' => $this->getRequestMethod(),
            'headers' => $this->getHeaders(),
            'post' => $this->getPostFields(),
            'get' => $this->getQueryFields(),
            'server' => $this->getServerInfo(),
            'remote' => $this->getRemoteInfo()
        );
    }

public function toArray ( ) { return array ( 'url' => $ this -> getRequestUrl ( ) , 'method' => $ this -> getRequestMethod ( ) , 'headers' => $ this -> getHeaders ( ) , 'post' => $ this -> getPostFields ( ) , 'get' => $ this -> getQueryFields ( ) , 'server' => $ this -> getServerInfo ( ) , 'remote' => $ this -> getRemoteInfo ( ) ) ; }

Returns a array with the values of this Request

@return array


public function addCommand(Command $command): void
    {
        $command->setMethod($command->getMethod() ?? static::RUN_METHOD);
        $dispatcher = $this->app->dispatcher();

        $dispatcher->verifyClassMethod($command);
        $dispatcher->verifyFunction($command);
        $dispatcher->verifyClosure($command);

        $this->addParsedCommand(
            $command,
            $this->app->pathParser()->parse(
                $command->getPath()
            )
        );
    }

public function addCommand ( Command $ command ) : void { $ command -> setMethod ( $ command -> getMethod ( ) ?? static :: RUN_METHOD ) ; $ dispatcher = $ this -> app -> dispatcher ( ) ; $ dispatcher -> verifyClassMethod ( $ command ) ; $ dispatcher -> verifyFunction ( $ command ) ; $ dispatcher -> verifyClosure ( $ command ) ; $ this -> addParsedCommand ( $ command , $ this -> app -> pathParser ( ) -> parse ( $ command -> getPath ( ) ) ) ; }

Add a new command.

@param Command $command The command

@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return void


protected function addParsedCommand(Command $command, array $parsedCommand): void
    {
        // Set the properties
        $command->setRegex($parsedCommand['regex']);
        $command->setParams($parsedCommand['params']);
        $command->setSegments($parsedCommand['segments']);

        // Set the command in the commands list
        self::$commands[$command->getPath()] = $command;
        // Set the command in the commands paths list
        self::$paths[$command->getRegex()] = $command->getPath();

        // If the command has a name
        if (null !== $command->getName()) {
            // Set in the named commands list to find it more easily later
            self::$namedCommands[$command->getName()] = $command->getPath();
        }
    }

Add a parsed command.

@param Command $command       The command
@param array   $parsedCommand The parsed command

@return void


public function command(string $name): ? Command
    {
        return $this->hasCommand($name)
            ? self::$commands[self::$namedCommands[$name]]
            : null;
    }

public function command ( string $ name ) : ? Command { return $ this -> hasCommand ( $ name ) ? self :: $ commands [ self :: $ namedCommands [ $ name ] ] : null ; }

Get a command by name.

@param string $name The command name

@return \Valkyrja\Console\Command


public function removeCommand(string $name): void
    {
        if ($this->hasCommand($name)) {
            unset(
                self::$commands[self::$namedCommands[$name]],
                self::$namedCommands[$name]
            );
        }
    }

public function removeCommand ( string $ name ) : void { if ( $ this -> hasCommand ( $ name ) ) { unset ( self :: $ commands [ self :: $ namedCommands [ $ name ] ] , self :: $ namedCommands [ $ name ] ) ; } }

Remove a command.

@param string $name The command name

@return void


public function matchCommand(string $path): Command
    {
        // If the path matches a set command path
        if (isset(self::$commands[$path])) {
            return self::$commands[$path];
        }

        $command = null;

        // Otherwise iterate through the commands and attempt to match via regex
        foreach (self::$paths as $regex => $commandPath) {
            // If the preg match is successful, we've found our command!
            if (preg_match($regex, $path, $matches)) {
                // Check if this command is provided
                if ($this->isProvided($commandPath)) {
                    // Initialize the provided command
                    $this->initializeProvided($commandPath);
                }

                // Clone the command to avoid changing the one set in the master
                // array
                $command = clone self::$commands[$commandPath];
                // The first match is the path itself
                unset($matches[0]);

                // Set the matches
                $command->setMatches($matches);

                return $command;
            }
        }

        // If a command was not found
        if (null === $command) {
            // Throw a not found exception
            throw new CommandNotFound('The command ' . $path . ' not found.');
        }

        return $command;
    }

Match a command by path.

@param string $path The path

@throws \Valkyrja\Console\Exceptions\CommandNotFound

@return \Valkyrja\Console\Command


public function all(): array
    {
        // Iterate through all the command providers to set any deferred
        // commands
        foreach (self::$provided as $provided => $provider) {
            // Initialize the provided command
            $this->initializeProvided($provided);
        }

        return self::$commands;
    }

Get all commands.

@return \Valkyrja\Console\Command[]


public function setup(bool $force = false, bool $useCache = true): void
    {
        // If the console was already setup no need to do it again
        if (self::$setup && ! $force) {
            return;
        }

        // The console is setting up
        self::$setup = true;

        // If the application should use the console cache files
        if ($useCache && $this->app->config()['console']['useCache']) {
            $this->setupFromCache();

            // Then return out of setup
            return;
        }

        self::$paths         = [];
        self::$commands      = [];
        self::$namedCommands = [];

        // Setup command providers
        $this->setupCommandProviders();

        // If annotations are enabled and the events should use annotations
        if (
            $this->app->config()['console']['useAnnotations']
            && $this->app->config()['annotations']['enabled']
        ) {
            // Setup annotated event listeners
            $this->setupAnnotations();

            // If only annotations should be used
            if ($this->app->config()['console']['useAnnotationsExclusively']) {
                // Return to avoid loading events file
                return;
            }
        }

        // Include the events file
        require $this->app->config()['console']['filePath'];
    }

Setup the console.

@param bool $force    [optional] Whether to force setup
@param bool $useCache [optional] Whether to use cache

@throws \ReflectionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return void


protected function setupFromCache(): void
    {
        // Set the application console with said file
        $cache = $this->app->config()['cache']['console']
            ?? require $this->app->config()['console']['cacheFilePath'];

        self::$commands      = unserialize(
            base64_decode($cache['commands'], true),
            [
                'allowed_classes' => [
                    Command::class,
                ],
            ]
        );
        self::$paths         = $cache['paths'];
        self::$namedCommands = $cache['namedCommands'];
        self::$provided      = $cache['provided'];
    }

Setup the console from cache.

@return void


public function getCacheable(): array
    {
        $this->setup(true, false);

        return [
            'commands'      => base64_encode(serialize(self::$commands)),
            'paths'         => self::$paths,
            'namedCommands' => self::$namedCommands,
            'provided'      => self::$provided,
        ];
    }

public function getCacheable ( ) : array { $ this -> setup ( true , false ) ; return [ 'commands' => base64_encode ( serialize ( self :: $ commands ) ) , 'paths' => self :: $ paths , 'namedCommands' => self :: $ namedCommands , 'provided' => self :: $ provided , ] ; }

Get a cacheable representation of the commands.

@throws \ReflectionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return array

Get a cacheable representation of the commands .


public function setSeparator($separator)
    {
        if ($separator == null) {

            throw new Zend_Filter_Exception('"' . $separator . '" is not a valid separator.');
        }
        $this->_separator = $separator;
        return $this;
    }

public
function
setSeparator
(
$
separator
)
{
if
(
$
separator
==
)
{
throw
new
Zend_Filter_Exception
(
'"'
.
$
separator
.
'" is not a valid separator.'
)
;
}
$
this
->
_separator
=
$
separator
;
return
$
this
;
}

Sets a new seperator

@param  string  $separator  Seperator
@return $this


public function listen(string $event, Listener $listener): void
    {
        $this->add($event);

        $this->app->dispatcher()->verifyDispatch($listener);

        // If this listener has an id
        if (null !== $listener->getId()) {
            // Use it when setting to allow removal
            // or checking if it exists later
            self::$events[$event][$listener->getId()] = $listener;
        } else {
            // Otherwise set the listener normally
            self::$events[$event][] = $listener;
        }
    }

public
function
listen
(
string
$
event
,
Listener
$
listener
)
:
void
{
$
this
->
add
(
$
event
)
;
$
this
->
app
->
dispatcher
(
)
->
verifyDispatch
(
$
listener
)
;
// If this listener has an id
if
(
!==
$
listener
->
getId
(
)
)
{
// Use it when setting to allow removal
// or checking if it exists later
self
::
$
events
[
$
event
]
[
$
listener
->
getId
(
)
]
=
$
listener
;
}
else
{
// Otherwise set the listener normally
self
::
$
events
[
$
event
]
[
]
=
$
listener
;
}
}

Add an event listener.

@param string   $event    The event
@param Listener $listener The event listener

@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return void


public function listenMany(Listener $listener, string ...$events): void
    {
        // Iterate through the events
        foreach ($events as $event) {
            // Set a new listener for the event
            $this->listen($event, $listener);
        }
    }

public
function
listenMany
(
Listener
$
listener
,
string
...
$
events
)
:
void
{
// Iterate through the events
foreach
(
$
events
as
$
event
)
{
// Set a new listener for the event
$
this
->
listen
(
$
event
,
$
listener
)
;
}
}

Add a listener to many events.

@param Listener $listener  The listener
@param string[] ...$events The events

@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return void


public function hasListener(string $event, string $listenerId): bool
    {
        return $this->has($event) && isset(self::$events[$event][$listenerId]);
    }

public function hasListener ( string $ event , string $ listenerId ) : bool { return $ this -> has ( $ event ) && isset ( self :: $ events [ $ event ] [ $ listenerId ] ) ; }

Determine whether an event has a specified listener.

@param string $event      The event
@param string $listenerId The event listener

@return bool

Determine whether an event has a specified listener .


public function removeListener(string $event, string $listenerId): void
    {
        // If the listener exists
        if ($this->hasListener($event, $listenerId)) {
            // Unset it
            unset(self::$events[$event][$listenerId]);
        }
    }

public
function
removeListener
(
string
$
event
,
string
$
listenerId
)
:
void
{
// If the listener exists
if
(
$
this
->
hasListener
(
$
event
,
$
listenerId
)
)
{
// Unset it
unset
(
self
::
$
events
[
$
event
]
[
$
listenerId
]
)
;
}
}

Remove an event listener.

@param string $event      The event
@param string $listenerId The event listener

@return void


public function hasListeners(string $event): bool
    {
        return $this->has($event) && ! empty(self::$events[$event]);
    }

public function hasListeners ( string $ event ) : bool { return $ this -> has ( $ event ) && ! empty ( self :: $ events [ $ event ] ) ; }

Determine whether an event has listeners.

@param string $event The event

@return bool

Determine whether an event has listeners .


public function add(string $event): void
    {
        if (! $this->has($event)) {
            self::$events[$event] = [];
        }
    }

public function add ( string $ event ) : void { if ( ! $ this -> has ( $ event ) ) { self :: $ events [ $ event ] = [ ] ; } }

Add a new event.

@param string $event The event

@return void


public function remove(string $event): void
    {
        if ($this->has($event)) {
            unset(self::$events[$event]);
        }
    }

public function remove ( string $ event ) : void { if ( $ this -> has ( $ event ) ) { unset ( self :: $ events [ $ event ] ) ; } }

Remove an event.

@param string $event The event

@return void


public function trigger(string $event, array $arguments = null): array
    {
        // The responses
        $responses = [];

        if (! $this->has($event) || ! $this->hasListeners($event)) {
            return $responses;
        }

        // Iterate through all the event's listeners
        foreach ($this->getListeners($event) as $listener) {
            // Attempt to dispatch the event listener using any one of the
            // callable options
            $dispatch = $this->app->dispatcher()->dispatchCallable(
                $listener,
                $arguments
            );

            if (null !== $dispatch) {
                $responses[] = $dispatch;
            }
        }

        return $responses;
    }

Trigger an event.

@param string $event     The event
@param array  $arguments [optional] The arguments

@return array


public function setup(bool $force = false, bool $useCache = true): void
    {
        if (self::$setup && ! $force) {
            return;
        }

        self::$setup = true;

        // If the application should use the events cache files
        if ($useCache && $this->app->config()['events']['useCache']) {
            $this->setupFromCache();

            // Then return out of setup
            return;
        }

        self::$events = [];

        // If annotations are enabled and the events should use annotations
        if (
            $this->app->config()['events']['useAnnotations']
            && $this->app->config()['annotations']['enabled']
        ) {
            // Setup annotated event listeners
            $this->setupAnnotations();

            // If only annotations should be used
            if ($this->app->config()['events']['useAnnotationsExclusively']) {
                // Return to avoid loading events file
                return;
            }
        }

        // Include the events file
        require $this->app->config()['events']['filePath'];
    }

Setup the events.

@param bool $force    [optional] Whether to force setup
@param bool $useCache [optional] Whether to use cache

@throws \Valkyrja\Dispatcher\Exceptions\InvalidClosureException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidDispatchCapabilityException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidFunctionException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidMethodException
@throws \Valkyrja\Dispatcher\Exceptions\InvalidPropertyException

@return void


protected function setupFromCache(): void
    {
        // Set the application events with said file
        $cache = $this->app->config()['cache']['events']
            ?? require $this->app->config()['events']['cacheFilePath'];

        self::$events = unserialize(
            base64_decode($cache['events'], true),
            [
                'allowed_classes' => [
                    Listener::class,
                ],
            ]
        );
    }

Setup the events from cache.

@return void


public function init($options) {

		$this->template = '';
		$this->template_data = '';

		$this->template_dir_orig = '';

		if ($options['templatepath'] != '') {
			$this->template_dir_orig = $options['templatepath'];
		}

		// compile dir is required and must be writable
		$this->compile_dir_orig  = $options['compiledir'];

		$this->caching = $options['usecache'];

		if ($this->caching) {
			$this->cache_dir    = $options['cachedir'];
		}

		$this->templates_extension = 'tpl';

		if ($options['extension'] != '') {
			$this->templates_extension = $options['extension'];
		}

		$this->initPlugins($options['templatingpluginsdir']);

		$this->template_vars = array();
	}

Init a template engine. Accepts array of options

templatepath - path to smarty templates directory
compiledir	- path to templates compilation directory
usecache	- (true|false) Torns cache On/Off .
cachedir	- If cache is On then directory for cache files
extension	- Extension of template files. Default is tpl
templatingpluginsdir - Path (or array of paths) to folders where Smarty extra plugins are stored

@param array $options

Init a template engine . Accepts array of options


public function checkTemplateExists($filepath,$options = array(),$tmplpath = '') {

		if (is_array($this->template_dir_orig) && $tmplpath == '') {
			foreach ($this->template_dir_orig as $path) {
				$exists = $this->checkTemplateExists($filepath,$options,$path);

				if ($exists) {
					return true;
				}
			}

			return false;
		}

		$filepath = (($tmplpath != '')?$tmplpath:$this->template_dir_orig).$filepath;

		if (!$options['extensionpresent']) {
			$filepath .= '.'.$this->templates_extension;
		}

		return file_exists($filepath);
	}

public function checkTemplateExists ( $ filepath , $ options = array ( ) , $ tmplpath = '' ) { if ( is_array ( $ this -> template_dir_orig ) && $ tmplpath == '' ) { foreach ( $ this -> template_dir_orig as $ path ) { $ exists = $ this -> checkTemplateExists ( $ filepath , $ options , $ path ) ; if ( $ exists ) { return true ; } } return false ; } $ filepath = ( ( $ tmplpath != '' ) ? $ tmplpath : $ this -> template_dir_orig ) . $ filepath ; if ( ! $ options [ 'extensionpresent' ] ) { $ filepath .= '.' . $ this -> templates_extension ; } return file_exists ( $ filepath ) ; }

Set template as string. It is HTML document to fetch later as a template

@paral string $filepath Template file name. Same rules as for setTemplate
@param array $options Array of options. Now only one option can eb used `extensionpresent` = true means template fiel path includes extension

@return boolean True if template file exists in a templates path

Set template as string . It is HTML document to fetch later as a template


public function fetchTemplate() {
		if ($this->template != '' &&
			$this->template_data == '' &&
			!$this->checkTemplateExists($this->template)) {

			throw new \Exception(sprintf('Template file %s not found',$this->template));
		}

		if ($this->template != '') {
			return $this->fetchFromFile();
		} else {
			return $this->fetchFromString();
		}
	}

public
function
fetchTemplate
(
)
{
if
(
$
this
->
template
!=
''
&&
$
this
->
template_data
==
''
&&
!
$
this
->
checkTemplateExists
(
$
this
->
template
)
)
{
throw
new
\
Exception
(
sprintf
(
'Template file %s not found'
,
$
this
->
template
)
)
;
}
if
(
$
this
->
template
!=
''
)
{
return
$
this
->
fetchFromFile
(
)
;
}
else
{
return
$
this
->
fetchFromString
(
)
;
}
}

Fetch prepared template and return complete html document

@return string HTML document with all data included


public function load(array $options = [])
    {
        $options = array_replace_recursive(
            $this->getOption('loadOptions', []),
            $options
        );

        // Simple shortcuts
        $options['readerOptions']['file'] = $options['readerOptions']['file'] ?? $options['file'];
        $options['readerOptions']['data'] = $options['readerOptions']['data'] ?? $options['data'];

        $reader = $this->getReader();
        $data = $reader->read($options['readerOptions']);

        if ($options['processImports'] && isset($data['import'])) {
            if (!is_array($data['import'])) {
                throw ImportException::create('"import" parameter must be an array.');
            }

            foreach ($data['import'] as $importData) {
                if (!is_array($importData)) {
                    throw ImportException::create('Each "import" array element must be an array.');
                }

                if (isset($importData['file'])) {
                    if ($options['file']) {
                        $importData['file'] = $importData['file']{0} === '/' ?
                            $importData['file'] :
                            dirname($options['file']).'/'.$importData['file'];
                    }

                    if (!is_file($importData['file'])) {
                        continue;
                    }
                }

                $readOptions = array_replace_recursive($options['readerOptions'], $importData);
                $data = array_replace_recursive($data, $reader->read($readOptions));
            }
        }

        if ($options['clearFirst']) {
            $this->setData([], false);
        }

        if ($options['loadInKey'] !== null) {
            if (!is_string($options['loadInKey'])) {
                throw InvalidOptionTypeException::create('loadInKey', 'string');
            }

            $this->set(
                $options['loadInKey'],
                $this->replaceTemplateVariables(array_replace_recursive($this->get($options['loadInKey'], []), $data))
            );
        } else {
            $this->setData(array_replace_recursive($this->getData(), $data));
        }

        /** @var Callable $callable */
        $callable = $this->getOption('onAfterLoad');

        if (!is_callable($callable)) {
            throw new \RuntimeException('Option "onAfterLoad" must be a callable.');
        }

        call_user_func_array($callable, [$this, $options]);

        return $this;
    }

Loads the configuration using the reader instance.

@param array $options - Options.

@throws InvalidOptionTypeException
@throws ImportException

@return $this

Loads the configuration using the reader instance .


public function save(array $options = [])
    {
        $options = array_merge(
            [
                'file'              => null,
                'writerOptions'     => []
            ],
            $options
        );

        // Simple shortcut
        $options['writerOptions']['file'] = $options['file'];

        /** @var Callable $callable */
        $callable = $this->getOption('onBeforeSave');

        if (!is_callable($callable)) {
            throw new \RuntimeException('Option "onBeforeSave" must be a callable.');
        }

        call_user_func_array($callable, [$this, $options]);

        $this->getWriter()->write($this->getData(), $options['writerOptions']);

        return $this;
    }

Saves the configuration with the writer instance.

@param array $options - Options.

@return $this

Saves the configuration with the writer instance .


protected function initializeReader()
    {
        $reader = $this->getOption('reader');

        if (is_string($reader)) {
            switch ($reader) {
                case 'array':
                    $reader = new ArrayReader();

                    break;
                case 'file':
                    $reader = new FileReader();

                    break;
                default:
                    throw new \InvalidArgumentException(
                        'Invalid reader "'.$reader.'". Valid reader strings: array, file.'
                    );
            }
        } else if (!is_object($reader) || !($reader instanceof ReaderInterface)) {
            throw new \InvalidArgumentException(
                'Option "reader" must be a string or an instance of IronEdge\Component\Config\Reader\ReaderInterface.'
            );
        }

        $this->setReader($reader);
    }

Initializes the reader instance.

@return void


protected function initializeWriter()
    {
        $writer = $this->getOption('writer');

        if (is_string($writer)) {
            switch ($writer) {
                case 'array':
                    $writer = new ArrayWriter();

                    break;
                case 'file':
                    $writer = new FileWriter();

                    break;
                default:
                    throw new \InvalidArgumentException(
                        'Invalid writer "'.$writer.'". Valid writer strings: array, file.'
                    );
            }
        } else if (!is_object($writer) || !($writer instanceof WriterInterface)) {
            throw new \InvalidArgumentException(
                'Option "writer" must be a string or an instance of IronEdge\Component\Config\Writer\WriterInterface.'
            );
        }

        $this->setWriter($writer);
    }

Initializes the writer instance.

@return void


public function getDefaultOptions(): array
    {
        return [
            'reader'                => 'file',
            'writer'                => 'file',
            'onAfterLoad'           => function(Config $config, array $options) {},
            'onBeforeSave'          => function(Config $config, array $options) {},
            'separator'             => '.',
            'templateVariables'     => [],
            'loadOptions'           => [
                'data'              => null,
                'file'              => null,
                'loadInKey'         => null,
                'processImports'    => false,
                'clearFirst'        => false,
                'readerOptions'     => []
            ]
        ];
    }

public function getDefaultOptions ( ) : array { return [ 'reader' => 'file' , 'writer' => 'file' , 'onAfterLoad' => function ( Config $ config , array $ options ) { } , 'onBeforeSave' => function ( Config $ config , array $ options ) { } , 'separator' => '.' , 'templateVariables' => [ ] , 'loadOptions' => [ 'data' => null , 'file' => null , 'loadInKey' => null , 'processImports' => false , 'clearFirst' => false , 'readerOptions' => [ ] ] ] ; }

Returns the default options.

@return array


protected function encrypt($data, $key)
    {
        $keySize = openssl_cipher_iv_length(static::CRYPT_MODE);
        $padding = $keySize - (mb_strlen($data, '8bit') % $keySize);
        /** @noinspection CryptographicallySecureRandomnessInspection */
        $iv   = openssl_random_pseudo_bytes($keySize);
        $key  = $this->generateKey($key);
        $data .= str_repeat(chr($padding), $padding);

        // add in our IV and base64 encode the data
        $data = base64_encode(
            $iv
            . openssl_encrypt(
                $data, static::CRYPT_MODE, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
            )
        );

        return $data;
    }

Encrypt the given data.

@param string $data Session data to encrypt.
@param string $key

@return string Encrypted data.


protected function decrypt($data, $key)
    {
        $base64 = base64_decode($data, true);

        $keySize = openssl_cipher_iv_length(static::CRYPT_MODE);
        $key     = $this->generateKey($key);

        $iv      = substr($base64, 0, $keySize);
        $results = substr($base64, $keySize);

        $results = openssl_decrypt(
            $results, static::CRYPT_MODE, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv
        );

        return $results;
    }

protected function decrypt ( $ data , $ key ) { $ base64 = base64_decode ( $ data , true ) ; $ keySize = openssl_cipher_iv_length ( static :: CRYPT_MODE ) ; $ key = $ this -> generateKey ( $ key ) ; $ iv = substr ( $ base64 , 0 , $ keySize ) ; $ results = substr ( $ base64 , $ keySize ) ; $ results = openssl_decrypt ( $ results , static :: CRYPT_MODE , $ key , OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING , $ iv ) ; return $ results ; }

Decrypt the given session data.

@param string $data Data to decrypt
@param string $key

@return string Decrypted data


protected function generateKey($key)
    {
        $keySize = openssl_cipher_iv_length(static::CRYPT_MODE);
        $key     = hash(
            'SHA256', $this->options->getClassName() . ':' . $this->sessionName . ':' . $key, true
        );

        return substr($key, 0, $keySize);
    }

protected function generateKey ( $ key ) { $ keySize = openssl_cipher_iv_length ( static :: CRYPT_MODE ) ; $ key = hash ( 'SHA256' , $ this -> options -> getClassName ( ) . ':' . $ this -> sessionName . ':' . $ key , true ) ; return substr ( $ key , 0 , $ keySize ) ; }

Generate secret key.

@param string $key

@return string Generated secret key


public function throwToStdout($exception, $full = true, $asJson = false)
    {
        $httpCode = method_exists($exception, 'getHttpCode') ? call_user_func([$exception, 'getHttpCode']) : 500;
        $logger = $this->getStdioLogger();
        $message = $this->getExceptionData($exception, $full, true);
        if ($logger) {
            $logger->error($message, [], 1);
        } else {
            echo $message;
        }
        if ($asJson) {
            $exceptionData = $this->getExceptionData($exception, $full, false);
        } else {
            $exceptionData = 'Error: ' . $exception->getMessage();
        }
        return $this->getResponse($httpCode, [], $exceptionData);
    }

public
function
throwToStdout
(
$
exception
,
$
full
=
true
,
$
asJson
=
false
)
{
$
httpCode
=
method_exists
(
$
exception
,
'getHttpCode'
)
call_user_func
(
[
$
exception
,
'getHttpCode'
]
)
:
500
;
$
logger
=
$
this
->
getStdioLogger
(
)
;
$
message
=
$
this
->
getExceptionData
(
$
exception
,
$
full
,
true
)
;
if
(
$
logger
)
{
$
logger
->
error
(
$
message
,
[
]
,
1
)
;
}
else
{
echo
$
message
;
}
if
(
$
asJson
)
{
$
exceptionData
=
$
this
->
getExceptionData
(
$
exception
,
$
full
,
false
)
;
}
else
{
$
exceptionData
=
'Error: '
.
$
exception
->
getMessage
(
)
;
}
return
$
this
->
getResponse
(
$
httpCode
,
[
]
,
$
exceptionData
)
;
}

Throw error description to Stdout
@param \Throwable $exception
@param bool       $full
@param bool       $asJson
@return Response


private function renderException($exception, $full = false)
    {
        $app = \Reaction::$app;
        try {
            $rendered = View::renderPhpStateless($this->getViewFileForException($exception), [
                'exceptionName' => $this->getExceptionName($exception),
                'exception' => $exception,
                'app' => $app,
                'rootPathLength' => strlen($app->getAlias('@root'))
            ]);
        } catch (\Throwable $e) {
            $rendered = $this->getExceptionData($exception, $full, true);
        }
        return $rendered;
    }

private function renderException ( $ exception , $ full = false ) { $ app = \ Reaction :: $ app ; try { $ rendered = View :: renderPhpStateless ( $ this -> getViewFileForException ( $ exception ) , [ 'exceptionName' => $ this -> getExceptionName ( $ exception ) , 'exception' => $ exception , 'app' => $ app , 'rootPathLength' => strlen ( $ app -> getAlias ( '@root' ) ) ] ) ; } catch ( \ Throwable $ e ) { $ rendered = $ this -> getExceptionData ( $ exception , $ full , true ) ; } return $ rendered ; }

Render exception view
@param \Throwable $exception
@param bool       $full
@return array|string


private function getViewFileForException($exception)
    {
        $basePath = \Reaction::$app->getAlias('@views/error');
        $tplName = 'general.php';
        if ($exception instanceof HttpExceptionInterface) {
            $code = $exception->statusCode;
        } else {
            $code = $exception->getCode();
        }
        if (file_exists($basePath . '/' . $code . '.php')) {
            $tplName = $code . '.php';
        }
        return $basePath . '/' . $tplName;
    }

private function getViewFileForException ( $ exception ) { $ basePath = \ Reaction :: $ app -> getAlias ( '@views/error' ) ; $ tplName = 'general.php' ; if ( $ exception instanceof HttpExceptionInterface ) { $ code = $ exception -> statusCode ; } else { $ code = $ exception -> getCode ( ) ; } if ( file_exists ( $ basePath . '/' . $ code . '.php' ) ) { $ tplName = $ code . '.php' ; } return $ basePath . '/' . $ tplName ; }

Get view file for exception depending on its code|httpStatusCode
@param \Throwable $exception
@return string


private function getResponse($code = 500, $headers = [], $body = null)
    {
        if (isset($body) && is_array($body)) {
            if (!isset($body['error'])) {
                $body = ['error' => $body];
            }
            $body = json_encode($body);
            $headers['Content-type'] = 'application/json';
        }
        return new Response($code, $headers, $body);
    }

private function getResponse ( $ code = 500 , $ headers = [ ] , $ body = null ) { if ( isset ( $ body ) && is_array ( $ body ) ) { if ( ! isset ( $ body [ 'error' ] ) ) { $ body = [ 'error' => $ body ] ; } $ body = json_encode ( $ body ) ; $ headers [ 'Content-type' ] = 'application/json' ; } return new Response ( $ code , $ headers , $ body ) ; }

Get error response
@param int    $code
@param string $body
@param array  $headers
@return Response


private function getExceptionData($exception, $full = false, $plainText = false)
    {
        if ($plainText) {
            $text = $exception->getMessage() . "\n";
            if ($full) {
                $text .= $exception->getFile() . " #" . $exception->getLine() . "\n";
                $text .= $exception->getTraceAsString() . "\n";
            }
            return $text;
        } else {
            $data = [
                'name' => $this->getExceptionName($exception),
                'message' => $exception->getMessage(),
                'code' => $exception->getCode(),
            ];
            if ($full) {
                $data = ArrayHelper::merge($data, [
                    'file' => $exception->getFile(),
                    'line' => $exception->getLine(),
                    'stacktrace' => $exception->getTrace(),
                ]);
            }
            return $data;
        }
    }

private
function
getExceptionData
(
$
exception
,
$
full
=
false
,
$
plainText
=
false
)
{
if
(
$
plainText
)
{
$
text
=
$
exception
->
getMessage
(
)
.
"\n"
;
if
(
$
full
)
{
$
text
.=
$
exception
->
getFile
(
)
.
" #"
.
$
exception
->
getLine
(
)
.
"\n"
;
$
text
.=
$
exception
->
getTraceAsString
(
)
.
"\n"
;
}
return
$
text
;
}
else
{
$
data
=
[
'name'
=>
$
this
->
getExceptionName
(
$
exception
)
,
'message'
=>
$
exception
->
getMessage
(
)
,
'code'
=>
$
exception
->
getCode
(
)
,
]
;
if
(
$
full
)
{
$
data
=
ArrayHelper
::
merge
(
$
data
,
[
'file'
=>
$
exception
->
getFile
(
)
,
'line'
=>
$
exception
->
getLine
(
)
,
'stacktrace'
=>
$
exception
->
getTrace
(
)
,
]
)
;
}
return
$
data
;
}
}

Get exception data as string or array
@param \Throwable $exception
@param bool       $full
@param bool       $plainText
@return array|string


private function getStdioLogger()
    {
        try {
            /** @var StdioLogger $logger */
            $logger = \Reaction::$di->get('stdioLogger');
        } catch (\Throwable $exception) {
            $logger = null;
        }
        return $logger;
    }

private
function
getStdioLogger
(
)
{
try
{
/** @var StdioLogger $logger */
$
logger
=
\
Reaction
::
$
di
->
get
(
'stdioLogger'
)
;
}
catch
(
\
Throwable
$
exception
)
{
$
logger
=
;
}
return
$
logger
;
}

Get StdioLogger instance
@return StdioLogger|null


public function read($id)
    {
        $key = $this->getSessionKey($id);
        return $this->getDataFromCache($key)->then(
            function($record) {
                return $this->extractData($record, true);
            }
        )->then(
            null,
            function($error = null) use ($id) {
                //return $self->restoreSessionData($id, true)->then(
                return $this->archive->get($id)->then(
                    function($data) use ($id, $error) {
                        if (is_array($data)) {
                            return $this->write($id, $data);
                        } else {
                            return \Reaction\Promise\reject($error);
                        }
                    }
                );
            }
        )->then(
            null,
            function($error = null) use ($id) {
                $message = sprintf('Failed to read session data for "%s"', $id);
                throw new SessionException($message, 0, $error);
            }
        );
    }

Read session data and returns serialized|encoded data
@param string $id
@return ExtendedPromiseInterface  with session data


public function write($id, $data)
    {
        $key = $this->getSessionKey($id);
        $record = $this->packRecord($data);
        return $this->writeDataToCache($key, $record)->then(
            function() use ($id) {
                $this->keys[$id] = time();
                return $this->read($id);
            },
            function($error = null) use ($id) {
                $message = sprintf('Failed to write session data for "%s"', $id);
                throw new SessionException($message, 0, $error);
            }
        );
    }

public
function
write
(
$
id
,
$
data
)
{
$
key
=
$
this
->
getSessionKey
(
$
id
)
;
$
record
=
$
this
->
packRecord
(
$
data
)
;
return
$
this
->
writeDataToCache
(
$
key
,
$
record
)
->
then
(
function
(
)
use
(
$
id
)
{
$
this
->
keys
[
$
id
]
=
time
(
)
;
return
$
this
->
read
(
$
id
)
;
}
,
function
(
$
error
=
)
use
(
$
id
)
{
$
message
=
sprintf
(
'Failed to write session data for "%s"'
,
$
id
)
;
throw
new
SessionException
(
$
message
,
0
,
$
error
)
;
}
)
;
}

Write session data to storage
@param string $id
@param array  $data
@return ExtendedPromiseInterface  with session data


public function destroy($id, $archiveRemove = false)
    {
        if (isset($this->keys[$id])) {
            unset($this->keys[$id]);
        }
        $key = $this->getSessionKey($id);
        return $this->cache->delete($key)->then(
            function() use ($id) { return $id; },
            function($error = null) use ($id) {
                $message = sprintf('Failed to destroy session "%s"', $id);
                throw new SessionException($message, 0, $error);
            }
        )->always(function() use ($id, $archiveRemove) {
            return $archiveRemove ? $this->archive->remove($id) : true;
        });
    }

public
function
destroy
(
$
id
,
$
archiveRemove
=
false
)
{
if
(
isset
(
$
this
->
keys
[
$
id
]
)
)
{
unset
(
$
this
->
keys
[
$
id
]
)
;
}
$
key
=
$
this
->
getSessionKey
(
$
id
)
;
return
$
this
->
cache
->
delete
(
$
key
)
->
then
(
function
(
)
use
(
$
id
)
{
return
$
id
;
}
,
function
(
$
error
=
)
use
(
$
id
)
{
$
message
=
sprintf
(
'Failed to destroy session "%s"'
,
$
id
)
;
throw
new
SessionException
(
$
message
,
0
,
$
error
)
;
}
)
->
always
(
function
(
)
use
(
$
id
,
$
archiveRemove
)
{
return
$
archiveRemove
$
this
->
archive
->
remove
(
$
id
)
:
true
;
}
)
;
}

Destroy a session
@param string $id The session ID being destroyed.
@param bool   $archiveRemove Remove data from archive or no
@return ExtendedPromiseInterface with bool when finished


public function updateTimestamp($id, $data = null)
    {
        $self = $this;
        return $this->read($id)->then(
            function($dataStored) use ($self, $id, $data) {
                if (isset($data)) {
                    $dataStored = $data;
                }
                return $self->write($id, $dataStored);
            }
        )->then(
            function() { return true; }
        );
    }

public function updateTimestamp ( $ id , $ data = null ) { $ self = $ this ; return $ this -> read ( $ id ) -> then ( function ( $ dataStored ) use ( $ self , $ id , $ data ) { if ( isset ( $ data ) ) { $ dataStored = $ data ; } return $ self -> write ( $ id , $ dataStored ) ; } ) -> then ( function ( ) { return true ; } ) ; }

Update timestamp of a session
@param string $id The session id
@param array  $data
The encoded session data. This data is the
result of the PHP internally encoding
the $_SESSION superglobal to a serialized
string and passing it as this parameter.
@return ExtendedPromiseInterface  with bool when finished


public function extractData($sessionRecord = [], $unserialize = false) {
        $data = isset($sessionRecord[$this->dataKey]) ? $sessionRecord[$this->dataKey] : [];
        return $unserialize && is_string($data) ? $this->unserializeData($data) : $data;
    }

public function extractData ( $ sessionRecord = [ ] , $ unserialize = false ) { $ data = isset ( $ sessionRecord [ $ this -> dataKey ] ) ? $ sessionRecord [ $ this -> dataKey ] : [ ] ; return $ unserialize && is_string ( $ data ) ? $ this -> unserializeData ( $ data ) : $ data ; }

Extract session data from record
@param array $sessionRecord
@param bool  $unserialize
@return array


protected function extractTimestamp($record = []) {
        return isset($record[$this->timestampKey]) ? $record[$this->timestampKey] : null;
    }

protected function extractTimestamp ( $ record = [ ] ) { return isset ( $ record [ $ this -> timestampKey ] ) ? $ record [ $ this -> timestampKey ] : null ; }

Extract session timestamp from record
@param array $record
@return integer|null


protected function getDataFromCache($key) {
        $self = $this;
        return (new Promise(function($r, $c) use ($self, $key) {
            $self->cache
                ->get($key)
                ->then(function($data) {
                    return $data !== null ? $data : reject(null);
                })->then(function($data) use ($r) {
                    $r($data);
                }, function() use ($c, $key) {
                    $message = sprintf('Failed to get session data from cache for "%s"', $key);
                    $c(new SessionException($message));
                });
        }));
    }

Get data from cache storage
@param string $key
@return ExtendedPromiseInterface


final public function getMessageWithVariables(): string
    {
        if (empty($this->message)) {
            throw new \Exception(sprintf(
                'Exception %s does not have a message',
                get_class($this)
            ), Level::CRITICAL);
        }

        $message = $this->message;

        preg_match_all(self::VARIABLE_REGEX, $message, $matches);

        foreach ($matches['variable'] as $variable) {
            $variableName = substr($variable, 1, -1);

            if (!isset($this->$variableName)) {
                throw new \Exception(sprintf(
                    'Variable "%s" for exception "%s" not found',
                    $variableName,
                    get_class($this)
                ), Level::CRITICAL);
            }

            if (!is_string($this->$variableName)) {
                throw new \Exception(sprintf(
                    'Variable "%s" for exception "%s" must be a string, %s found',
                    $variableName,
                    get_class($this),
                    gettype($this->$variableName)
                ), Level::CRITICAL);
            }

            $message = str_replace($variable, $this->$variableName, $message);
        }

        return $message;
    }

Get message with variables

@throws \Exception

@return string


private final function constraint(TableInterface $table): string
    {
        $mySql = $selfKey = $foreignKey = "";
        $name = $table->get($table::ATTR_NAME);
        foreach ($table->get($table::ATTR_KEY) as $key => $value) {
            if (KeyInterface::FOREIGN !== $value->getType()) {
                $selfKey .= $this->addKey($value, $name . "_" . $key);
                if (KeyInterface::PRIMARY === $value->getType()) {
                    foreach ($value->getSubject() as $key) {
                        $selfKey .= $this->addAutoIncrement(
                            $key,
                            $table->get($table::ATTR_COLUMN));
                    }
                }
                continue;
            }
            $foreignKey .= $this->addForeign($value, $name . "_" . $key);
        }
        foreach ([$selfKey, $foreignKey] as $value) {
            $mySql .= $value ? "ALTER TABLE `" . $name . "`\n"
                             . substr($value, 0, -2) . ";\n"
                             : $value;
        }
        return substr($mySql, 0, -1);
    }

private
final
function
constraint
(
TableInterface
$
table
)
:
string
{
$
mySql
=
$
selfKey
=
$
foreignKey
=
""
;
$
name
=
$
table
->
get
(
$
table
::
ATTR_NAME
)
;
foreach
(
$
table
->
get
(
$
table
::
ATTR_KEY
)
as
$
key
=>
$
value
)
{
if
(
KeyInterface
::
FOREIGN
!==
$
value
->
getType
(
)
)
{
$
selfKey
.=
$
this
->
addKey
(
$
value
,
$
name
.
"_"
.
$
key
)
;
if
(
KeyInterface
::
PRIMARY
===
$
value
->
getType
(
)
)
{
foreach
(
$
value
->
getSubject
(
)
as
$
key
)
{
$
selfKey
.=
$
this
->
addAutoIncrement
(
$
key
,
$
table
->
get
(
$
table
::
ATTR_COLUMN
)
)
;
}
}
continue
;
}
$
foreignKey
.=
$
this
->
addForeign
(
$
value
,
$
name
.
"_"
.
$
key
)
;
}
foreach
(
[
$
selfKey
,
$
foreignKey
]
as
$
value
)
{
$
mySql
.=
$
value
"ALTER TABLE `"
.
$
name
.
"`\n"
.
substr
(
$
value
,
0
,
2
)
.
";\n"
:
$
value
;
}
return
substr
(
$
mySql
,
0
,
1
)
;
}

Get constraint syntaxe

@param TableInterface $table table
@return string constraint syntaxe


private final function addAutoIncrement(string $key, array $column): string
    {
        $autoIncrement = "";
        if (array_key_exists($key, $column) && in_array(
                ColumnInterface::OPT_AUTO_INCREMENT,
                $column[$key]->getOption())) {
            $autoIncrement .= "MODIFY "
                 . substr($this->getColumnSyntaxe($column[$key]), 0, -2)
                 . " AUTO_INCREMENT,\n";
        }
        return $autoIncrement;
    }

private
final
function
addAutoIncrement
(
string
$
key
,
array
$
column
)
:
string
{
$
autoIncrement
=
""
;
if
(
array_key_exists
(
$
key
,
$
column
)
&&
in_array
(
ColumnInterface
::
OPT_AUTO_INCREMENT
,
$
column
[
$
key
]
->
getOption
(
)
)
)
{
$
autoIncrement
.=
"MODIFY "
.
substr
(
$
this
->
getColumnSyntaxe
(
$
column
[
$
key
]
)
,
0
,
2
)
.
" AUTO_INCREMENT,\n"
;
}
return
$
autoIncrement
;
}

Add auto increment

@param string $key
@param array $column
@return string modify auto increment syntax


private final function addKey(KeyInterface $key, string $name): string
    {
        return "ADD " . $this->constant($key->getType())
             . " `k_" . $name . "`"
             . " (`" . implode("`, `", ($key->getSubject())) . "`),\n";
    }

private
final
function
addKey
(
KeyInterface
$
key
,
string
$
name
)
:
string
{
return
"ADD "
.
$
this
->
constant
(
$
key
->
getType
(
)
)
.
" `k_"
.
$
name
.
"`"
.
" (`"
.
implode
(
"`, `"
,
(
$
key
->
getSubject
(
)
)
)
.
"`),\n"
;
}

Get add key syntaxe

@param KeyInterface $key key
@param string $name name
@return string add key syntaxe


private final function addForeign(KeyInterface $key, string $name): string
    {
        return "ADD CONSTRAINT" . " `fk_" . $name . "`"
             . " " . $this->constant($key->getType())
             . " (`" . implode("`, `", ($key->getSubject())) . "`) "
             . " REFERENCES `" . $key->getForeigner() . "`"
             . " (`" . implode("`, `", ($key->getForeignerSubject())) . "`),\n";
    }

private
final
function
addForeign
(
KeyInterface
$
key
,
string
$
name
)
:
string
{
return
"ADD CONSTRAINT"
.
" `fk_"
.
$
name
.
"`"
.
" "
.
$
this
->
constant
(
$
key
->
getType
(
)
)
.
" (`"
.
implode
(
"`, `"
,
(
$
key
->
getSubject
(
)
)
)
.
"`) "
.
" REFERENCES `"
.
$
key
->
getForeigner
(
)
.
"`"
.
" (`"
.
implode
(
"`, `"
,
(
$
key
->
getForeignerSubject
(
)
)
)
.
"`),\n"
;
}

Get add foreign key syntaxe

@param KeyInterface $key key
@param string $name name
@return string add foreign key syntaxe


private final function getColumnSyntaxe(ColumnInterface $column)
    {
        $mySql = "`" . $column->getName() . "` "
               . $this->constant($column->getType())
               . "(" . $column->getSize() . ")";
        foreach ($column->getOption() as $option) {
            $const = $this->constant($option);
            $mySql .= $const ? " " . $const : "";
        }
        return $mySql . ",\n";
    }

private
final
function
getColumnSyntaxe
(
ColumnInterface
$
column
)
{
$
mySql
=
"`"
.
$
column
->
getName
(
)
.
"` "
.
$
this
->
constant
(
$
column
->
getType
(
)
)
.
"("
.
$
column
->
getSize
(
)
.
")"
;
foreach
(
$
column
->
getOption
(
)
as
$
option
)
{
$
const
=
$
this
->
constant
(
$
option
)
;
$
mySql
.=
$
const
" "
.
$
const
:
""
;
}
return
$
mySql
.
",\n"
;
}

Get column syntax

@param ColumnInterface $column
@return string column syntax line


public function jumpstart()
    {
        $this->getLoader()->action('activate_' . $this->getBasename(), array($this, 'activate'));
        $this->getLoader()->action('deactivate_' . $this->getBasename(), array($this, 'deactivate'));
        $this->getLoader()->action('uninstall_' . $this->getBasename(), array($this, 'uninstall'));
        $this->getLoader()->run();
    }

public function jumpstart ( ) { $ this -> getLoader ( ) -> action ( 'activate_' . $ this -> getBasename ( ) , array ( $ this , 'activate' ) ) ; $ this -> getLoader ( ) -> action ( 'deactivate_' . $ this -> getBasename ( ) , array ( $ this , 'deactivate' ) ) ; $ this -> getLoader ( ) -> action ( 'uninstall_' . $ this -> getBasename ( ) , array ( $ this , 'uninstall' ) ) ; $ this -> getLoader ( ) -> run ( ) ; }

Run the loader to execute all of the hooks with WordPress.

@since       1.0.0

Run the loader to execute all of the hooks with WordPress .


protected function _createIterationException(
        $message = null,
        $code = null,
        RootException $previous = null,
        IterationInterface $iteration = null
    ) {
        return new IterationException($message, $code, $previous, $iteration);
    }

protected function _createIterationException ( $ message = null , $ code = null , RootException $ previous = null , IterationInterface $ iteration = null ) { return new IterationException ( $ message , $ code , $ previous , $ iteration ) ; }

Creates a new iteration exception instance.

@since [*next-version*]

@param string|Stringable|null  $message   The error message, if any.
@param int|null                $code      The error code, if any.
@param RootException|null      $previous  The previous exception for chaining, if any.
@param IterationInterface|null $iteration The iteration instance, if any.

@return IterationException The created exception instance.

Creates a new iteration exception instance .


protected function renderToggleButton()
    {
        $icon = $this->htmlHlp->tag('span', '', ['class' => 'navbar-toggler-icon']);
        $screenReader = isset($this->screenReaderToggleText)
            ? "{$this->screenReaderToggleText}"
            : '';

        return $this->htmlHlp->button("{$screenReader}\n{$icon}", [
            'class' => 'navbar-toggler',
            'data-toggle' => 'collapse',
            'data-target' => "#{$this->containerOptions['id']}",
        ]);
    }

Renders collapsible toggle button.
@return string the rendering toggle button.


protected function getResponse($templateName, $isNaked = false)
    {
        $this->response = new ResponseTemplate();

        $content = $this->getTemplate($templateName);

        if (!$isNaked) {
            $content = $this->getLayout($content);
        }

        $this->response->setHttpCode(200)->setContent($content);

        return $this->response;
    }

protected function getResponse ( $ templateName , $ isNaked = false ) { $ this -> response = new ResponseTemplate ( ) ; $ content = $ this -> getTemplate ( $ templateName ) ; if ( ! $ isNaked ) { $ content = $ this -> getLayout ( $ content ) ; } $ this -> response -> setHttpCode ( 200 ) -> setContent ( $ content ) ; return $ this -> response ; }

Get Response object

@param  string $templateName
@param  bool $isNaked
@return ResponseInterface


protected function getModuleName()
    {
        if (empty($this->appModuleName)) {
            $className = trim(get_class($this));
            $namespace = substr(__NAMESPACE__, 0, strrpos(__NAMESPACE__, '\\'));
            $namespace = substr($namespace, 0, strrpos($namespace, '\\')) . '\Module\\';
            $className = trim(str_replace(array($namespace), array(''), $className));

            $this->appModuleName = substr($className, 0, strpos($className, '\\'));
        }

        return $this->appModuleName;
    }

protected function getModuleName ( ) { if ( empty ( $ this -> appModuleName ) ) { $ className = trim ( get_class ( $ this ) ) ; $ namespace = substr ( __NAMESPACE__ , 0 , strrpos ( __NAMESPACE__ , '\\' ) ) ; $ namespace = substr ( $ namespace , 0 , strrpos ( $ namespace , '\\' ) ) . '\Module\\' ; $ className = trim ( str_replace ( array ( $ namespace ) , array ( '' ) , $ className ) ) ; $ this -> appModuleName = substr ( $ className , 0 , strpos ( $ className , '\\' ) ) ; } return $ this -> appModuleName ; }


public static function loadClassReflection($class)
    {
        if (is_object($class)) {
            $class = get_class($class);
        }

        if (isset(self::$classReflections[$class])) {
            return self::$classReflections[$class];
        }

        $reflection = new \ReflectionClass($class);

        self::$classReflections[$class] = $reflection;

        return $reflection;
    }

public static function loadClassReflection ( $ class ) { if ( is_object ( $ class ) ) { $ class = get_class ( $ class ) ; } if ( isset ( self :: $ classReflections [ $ class ] ) ) { return self :: $ classReflections [ $ class ] ; } $ reflection = new \ ReflectionClass ( $ class ) ; self :: $ classReflections [ $ class ] = $ reflection ; return $ reflection ; }

Load class reflection

@param string|object $class

@return \ReflectionClass


public static function loadObjectReflection($object)
    {
        if (!is_object($object)) {
            throw new \InvalidArgumentException(sprintf(
                'Could not load reflection for non object. Given: "%s".',
                gettype($object)
            ));
        }

        $hash = spl_object_hash($object);

        if (isset(self::$objectReflections[$hash])) {
            return self::$objectReflections[$hash];
        }

        $reflection = new \ReflectionObject($object);

        self::$objectReflections[$hash] = $reflection;

        return $reflection;
    }

Load object reflection

@param object $object

@return \ReflectionObject


public static function loadPropertyReflection($object, $property, $searchInParents = true)
    {
        $reflection = self::loadClassReflection($object);

        if (!$searchInParents) {
            return $reflection->getProperty($property);
        }

        $exception = null;

        do {
            try {
                $reflectionProperty = $reflection->getProperty($property);

                return $reflectionProperty;
            } catch (\ReflectionException $e) {
                if (!$exception) {
                    $exception = $e;
                }
            }
        } while ($reflection = $reflection->getParentClass());

        throw $exception;
    }

public static function loadPropertyReflection ( $ object , $ property , $ searchInParents = true ) { $ reflection = self :: loadClassReflection ( $ object ) ; if ( ! $ searchInParents ) { return $ reflection -> getProperty ( $ property ) ; } $ exception = null ; do { try { $ reflectionProperty = $ reflection -> getProperty ( $ property ) ; return $ reflectionProperty ; } catch ( \ ReflectionException $ e ) { if ( ! $ exception ) { $ exception = $ e ; } } } while ( $ reflection = $ reflection -> getParentClass ( ) ) ; throw $ exception ; }

Load property reflection

@param object $object
@param string $property
@param bool   $searchInParents

@return \ReflectionProperty

@throws \ReflectionException


public static function getCalledMethod(\ReflectionFunctionAbstract $method, $closureInfo = true)
    {
        if ($method->isClosure()) {
            if ($closureInfo) {
                return sprintf(
                    'Closure [%s:%d]',
                    $method->getFileName(),
                    $method->getStartLine()
                );
            }

            return 'Closure';
        }

        if ($method instanceof \ReflectionMethod) {
            return sprintf(
                '%s::%s',
                $method->getDeclaringClass()->getName(),
                $method->getName()
            );
        }

        return $method->getName();
    }

public
static
function
getCalledMethod
(
\
ReflectionFunctionAbstract
$
method
,
$
closureInfo
=
true
)
{
if
(
$
method
->
isClosure
(
)
)
{
if
(
$
closureInfo
)
{
return
sprintf
(
'Closure [%s:%d]'
,
$
method
->
getFileName
(
)
,
$
method
->
getStartLine
(
)
)
;
}
return
'Closure'
;
}
if
(
$
method
instanceof
\
ReflectionMethod
)
{
return
sprintf
(
'%s::%s'
,
$
method
->
getDeclaringClass
(
)
->
getName
(
)
,
$
method
->
getName
(
)
)
;
}
return
$
method
->
getName
(
)
;
}

Get called method from abstract reflection function

@param \ReflectionFunctionAbstract $method
@param bool                        $closureInfo

@return string


public static function getClassProperties($class, $inParents = false, $filter = null)
    {
        if ($filter === null) {
            $filter = \ReflectionProperty::IS_PRIVATE
                | \ReflectionProperty::IS_PROTECTED
                | \ReflectionProperty::IS_PUBLIC;
        }

        $reflection = self::loadClassReflection($class);

        if (!$inParents) {
            return $reflection->getProperties($filter);
        }

        $properties = [];

        do {
            $properties = array_merge(
                $reflection->getProperties($filter),
                $properties
            );
        } while ($reflection = $reflection->getParentClass());

        return $properties;
    }

public static function getClassProperties ( $ class , $ inParents = false , $ filter = null ) { if ( $ filter === null ) { $ filter = \ ReflectionProperty :: IS_PRIVATE | \ ReflectionProperty :: IS_PROTECTED | \ ReflectionProperty :: IS_PUBLIC ; } $ reflection = self :: loadClassReflection ( $ class ) ; if ( ! $ inParents ) { return $ reflection -> getProperties ( $ filter ) ; } $ properties = [ ] ; do { $ properties = array_merge ( $ reflection -> getProperties ( $ filter ) , $ properties ) ; } while ( $ reflection = $ reflection -> getParentClass ( ) ) ; return $ properties ; }

Get class properties

@param string $class
@param bool   $inParents
@param int    $filter

@return \ReflectionProperty[]


public static function setPropertyValue($object, $property, $value)
    {
        $ref = self::loadClassReflection($object);

        $refProperty = $ref->getProperty($property);

        if (!$refProperty->isPublic()) {
            $refProperty->setAccessible(true);
        }

        if ($refProperty->isStatic()) {
            $refProperty->setValue($value);
        } else {
            $refProperty->setValue($object, $value);
        }
    }

public static function setPropertyValue ( $ object , $ property , $ value ) { $ ref = self :: loadClassReflection ( $ object ) ; $ refProperty = $ ref -> getProperty ( $ property ) ; if ( ! $ refProperty -> isPublic ( ) ) { $ refProperty -> setAccessible ( true ) ; } if ( $ refProperty -> isStatic ( ) ) { $ refProperty -> setValue ( $ value ) ; } else { $ refProperty -> setValue ( $ object , $ value ) ; } }

Set value to property

@param object|string $object
@param string        $property
@param mixed  $value


public static function setPropertiesValue($object, array $properties)
    {
        foreach ($properties as $name => $value) {
            self::setPropertyValue($object, $name, $value);
        }
    }

public static function setPropertiesValue ( $ object , array $ properties ) { foreach ( $ properties as $ name => $ value ) { self :: setPropertyValue ( $ object , $ name , $ value ) ; } }

Set value to properties

@param object|string $object
@param array         $properties


public static function loadClassAnnotations(Reader $reader, $class, $inParents = false)
    {
        $reflection = self::loadClassReflection($class);

        if (!$inParents) {
            return $reader->getClassAnnotations($reflection);
        }

        $annotations = [];

        do {
            $classAnnotations = $reader->getClassAnnotations($reflection);

            foreach ($classAnnotations as $classAnnotation) {
                if (!isset($annotations[get_class($classAnnotation)])) {
                    $annotations[get_class($classAnnotation)] = $classAnnotation;
                }
            }
        } while ($reflection = $reflection->getParentClass());

        return array_values($annotations);
    }

public static function loadClassAnnotations ( Reader $ reader , $ class , $ inParents = false ) { $ reflection = self :: loadClassReflection ( $ class ) ; if ( ! $ inParents ) { return $ reader -> getClassAnnotations ( $ reflection ) ; } $ annotations = [ ] ; do { $ classAnnotations = $ reader -> getClassAnnotations ( $ reflection ) ; foreach ( $ classAnnotations as $ classAnnotation ) { if ( ! isset ( $ annotations [ get_class ( $ classAnnotation ) ] ) ) { $ annotations [ get_class ( $ classAnnotation ) ] = $ classAnnotation ; } } } while ( $ reflection = $ reflection -> getParentClass ( ) ) ; return array_values ( $ annotations ) ; }

Load class annotations

@param Reader        $reader
@param string|object $class
@param bool          $inParents

@return array


public static function clear($mode = null)
    {
        if (is_numeric($mode)) {
            $mode = self::TYPE_CLASS | self::TYPE_OBJECT;
        }

        if ($mode & self::TYPE_CLASS) {
            self::$classReflections = array();
        }

        if ($mode & self::TYPE_OBJECT) {
            self::$objectReflections = array();
        }
    }

public static function clear ( $ mode = null ) { if ( is_numeric ( $ mode ) ) { $ mode = self :: TYPE_CLASS | self :: TYPE_OBJECT ; } if ( $ mode & self :: TYPE_CLASS ) { self :: $ classReflections = array ( ) ; } if ( $ mode & self :: TYPE_OBJECT ) { self :: $ objectReflections = array ( ) ; } }

Clear internal storage

@param int $mode


public static function isInstantiable($className)
    {
        $reflection = static::getClassReflection($className);
        if ($reflection === null) {
            return false;
        }
        return $reflection->isInstantiable();
    }

public static function isInstantiable ( $ className ) { $ reflection = static :: getClassReflection ( $ className ) ; if ( $ reflection === null ) { return false ; } return $ reflection -> isInstantiable ( ) ; }

Check that class is instantiable
@param string $className
@return bool


public static function getMethodReflection($objectOrName, $methodName)
    {
        $cached = static::getReflectionFromCache(static::REFLECTION_METHOD, $objectOrName, $methodName);
        if ($cached !== null) {
            return $cached;
        }
        try {
            $reflection = new \ReflectionMethod($objectOrName, $methodName);
            return static::setReflectionToCache($reflection, static::REFLECTION_METHOD, $objectOrName, $methodName);
        } catch (\ReflectionException $exception) {
            $reflection = null;
        }
        return $reflection;
    }

public static function getMethodReflection ( $ objectOrName , $ methodName ) { $ cached = static :: getReflectionFromCache ( static :: REFLECTION_METHOD , $ objectOrName , $ methodName ) ; if ( $ cached !== null ) { return $ cached ; } try { $ reflection = new \ ReflectionMethod ( $ objectOrName , $ methodName ) ; return static :: setReflectionToCache ( $ reflection , static :: REFLECTION_METHOD , $ objectOrName , $ methodName ) ; } catch ( \ ReflectionException $ exception ) { $ reflection = null ; } return $ reflection ; }

Get class method reflection
@param string|object $objectOrName
@param string $methodName
@return null|\ReflectionMethod


public static function getClassReflection($objectOrName)
    {
        $cached = static::getReflectionFromCache(static::REFLECTION_CLASS, $objectOrName);
        if ($cached !== null) {
            return $cached;
        }
        try {
            $reflection = new \ReflectionClass($objectOrName);
            return static::setReflectionToCache($reflection, static::REFLECTION_CLASS, $objectOrName);
        } catch (\ReflectionException $exception) {
            $reflection = null;
        }
        return $reflection;
    }

public static function getClassReflection ( $ objectOrName ) { $ cached = static :: getReflectionFromCache ( static :: REFLECTION_CLASS , $ objectOrName ) ; if ( $ cached !== null ) { return $ cached ; } try { $ reflection = new \ ReflectionClass ( $ objectOrName ) ; return static :: setReflectionToCache ( $ reflection , static :: REFLECTION_CLASS , $ objectOrName ) ; } catch ( \ ReflectionException $ exception ) { $ reflection = null ; } return $ reflection ; }

Get class reflection
@param string|object $objectOrName
@return null|\ReflectionClass


public static function checkMethodArguments($arguments = [], $method, $objectOrName = null, $returnType = self::ARG_CHECK_RETURN_DATA)
    {
        if ($method instanceof \ReflectionMethod) {
            $reflection = $method;
        } elseif ($objectOrName !== null) {
            $reflection = static::getMethodReflection($objectOrName, $method);
        } else {
            return null;
        }
        if ($reflection->getNumberOfRequiredParameters() === 0) {
            return $returnType === static::ARG_CHECK_RETURN_DATA ? [] : true;
        }
        $methodParams = $reflection->getParameters();
        $data = [];
        foreach ($methodParams as $param) {
            if (!$param->isOptional() && empty($arguments)) {
                $data[$param->name] = static::ARG_REQUIRED_MISSING;
            } elseif(!empty($arguments) && ($type = $param->getType()) !== null) {
                $arg = reset($arguments);
                $typeName = $type->getName();
                $stdTypes = ['bool', 'int', 'string', 'array', 'object', 'float', 'callable'];
                if (!in_array($typeName, $stdTypes) && !$arg instanceof $typeName) {
                    $data[$param->name] = static::ARG_TYPE_MISMATCH;
                }
            }
            array_shift($arguments);
        }
        return $returnType === static::ARG_CHECK_RETURN_DATA ? $data : empty($data);
    }

public static function checkMethodArguments ( $ arguments = [ ] , $ method , $ objectOrName = null , $ returnType = self :: ARG_CHECK_RETURN_DATA ) { if ( $ method instanceof \ ReflectionMethod ) { $ reflection = $ method ; } elseif ( $ objectOrName !== null ) { $ reflection = static :: getMethodReflection ( $ objectOrName , $ method ) ; } else { return null ; } if ( $ reflection -> getNumberOfRequiredParameters ( ) === 0 ) { return $ returnType === static :: ARG_CHECK_RETURN_DATA ? [ ] : true ; } $ methodParams = $ reflection -> getParameters ( ) ; $ data = [ ] ; foreach ( $ methodParams as $ param ) { if ( ! $ param -> isOptional ( ) && empty ( $ arguments ) ) { $ data [ $ param -> name ] = static :: ARG_REQUIRED_MISSING ; } elseif ( ! empty ( $ arguments ) && ( $ type = $ param -> getType ( ) ) !== null ) { $ arg = reset ( $ arguments ) ; $ typeName = $ type -> getName ( ) ; $ stdTypes = [ 'bool' , 'int' , 'string' , 'array' , 'object' , 'float' , 'callable' ] ; if ( ! in_array ( $ typeName , $ stdTypes ) && ! $ arg instanceof $ typeName ) { $ data [ $ param -> name ] = static :: ARG_TYPE_MISMATCH ; } } array_shift ( $ arguments ) ; } return $ returnType === static :: ARG_CHECK_RETURN_DATA ? $ data : empty ( $ data ) ; }

Check class method arguments for consistency
@param array  $arguments
@param string|\ReflectionMethod $method
@param null   $objectOrName
@param string $returnType
@return array|bool|null


protected static function getReflectionFromCache($type = self::REFLECTION_CLASS, $objectOrName, ...$params)
    {
        $cache = &static::$_reflections[$type];
        $key = static::getCacheKey($type, $objectOrName, ...$params);
        return isset($cache[$key]) ? $cache[$key] : null;
    }

protected static function getReflectionFromCache ( $ type = self :: REFLECTION_CLASS , $ objectOrName , ... $ params ) { $ cache = & static :: $ _reflections [ $ type ] ; $ key = static :: getCacheKey ( $ type , $ objectOrName , ... $ params ) ; return isset ( $ cache [ $ key ] ) ? $ cache [ $ key ] : null ; }

Get reflection from cache
@param string $type
@param string|object $objectOrName
@param mixed  ...$params
@return mixed


protected static function setReflectionToCache($reflection, $type = self::REFLECTION_CLASS, $objectOrName = null, ...$params)
    {
        if (null === $reflection || null === $objectOrName) {
            return null;
        }
        $key = static::getCacheKey($type, $objectOrName, ...$params);
        static::$_reflections[$type][$key] = $reflection;
        return $reflection;
    }

protected static function setReflectionToCache ( $ reflection , $ type = self :: REFLECTION_CLASS , $ objectOrName = null , ... $ params ) { if ( null === $ reflection || null === $ objectOrName ) { return null ; } $ key = static :: getCacheKey ( $ type , $ objectOrName , ... $ params ) ; static :: $ _reflections [ $ type ] [ $ key ] = $ reflection ; return $ reflection ; }

Save reflection to cache
@param \Reflector $reflection
@param string     $type
@param null       $objectOrName
@param mixed      ...$params
@return mixed


protected static function getCacheKey($type = self::REFLECTION_CLASS, $objectOrName, ...$params)
    {
        if (is_object($objectOrName)) {
            $className = static::getObjectClassName($objectOrName);
        } else {
            $className = $objectOrName;
        }
        $key = $className;
        switch ($type) {
            case static::REFLECTION_METHOD:
            case static::REFLECTION_PROPERTY:
                $methodOrProperty = $params[0];
                $key .= '::' . $methodOrProperty;
                break;
        }
        return $key;
    }

protected static function getCacheKey ( $ type = self :: REFLECTION_CLASS , $ objectOrName , ... $ params ) { if ( is_object ( $ objectOrName ) ) { $ className = static :: getObjectClassName ( $ objectOrName ) ; } else { $ className = $ objectOrName ; } $ key = $ className ; switch ( $ type ) { case static :: REFLECTION_METHOD : case static :: REFLECTION_PROPERTY : $ methodOrProperty = $ params [ 0 ] ; $ key .= '::' . $ methodOrProperty ; break ; } return $ key ; }

Get object cache key
@param string $type
@param string|object $objectOrName
@param mixed[]  ...$params
@return mixed|string